/******************************************************************************
 * * hal_wlan.c - realize wlan functions
 * * note: allow to perform opening ap and scaning at the same time;
 * *       trigger to scan when wakeup,sleep,open wlan ui,turn on wlan and ap disconnected.
 * *(C) Copyright 2020 Asr International Ltd.
 * * All Rights Reserved
 * ******************************************************************************/

/*********************
 *      INCLUDES
 *********************/
#include <stdio.h>
#include <stdlib.h>
#include "hal_wlan.h"

#if USE_LV_WLAN != 0

#include "wlan_inc/wlan_sta_api.h"
#include "wlan_inc/lwip_api.h"

/*********************
 *      DEFINES
 *********************/
#ifndef GUI_TASK_PRIORITY
#define GUI_TASK_PRIORITY                      200
#endif

#define HAL_WLAN_ADP_TASK_MSGQSIZE             32
#define HAL_WLAN_ADP_TASK_STACKSIZE            4 * 1000
#define HAL_WLAN_ADP_TASK_PRIORITY             (GUI_TASK_PRIORITY + 1)

/* the interval for periodic scan */
#define HAL_WLAN_PERIODIC_SCAN_INTERVAL_MS     10000
#define HAL_WLAN_RESCAN_INTERVAL               1      /* interval in wlan ui if lcd on */
#define HAL_WLAN_MIN_PERIODIC_SCAN_INTERVAL    2
#define HAL_WLAN_MAX_PERIODIC_SCAN_INTERVAL    16

#define HAL_WLAN_NVM_PATH                      "C:/ui_wlan.nv"

#define HAL_WLAN_RSSI_MIN                      -100
#define HAL_WLAN_RSSI_MAX                      -55
#define HAL_WLAN_RSSI_RANGE                    (HAL_WLAN_RSSI_MAX - HAL_WLAN_RSSI_MIN)

#define HAL_WLAN_GET_IP_TIMER_LEN              500 // in ms
#define HAL_WLAN_GET_IP_MAX_TIMEOUT_COUNT      40  // 20s

#define HAL_WLAN_CHECK_SDIO_CONFIG_INTERVAL    200 // in ms
#define HAL_WLAN_MAX_CHECK_SDIO_CONFIG_COUNT   20

#define HAL_WLAN_MAX_TRY_NUM                   2   // not 0
#define HAL_WLAN_MAX_CONN_NUM                  5   // not 0

#define HAL_WLAN_DEFAULT_AUTO_SEL_NW           0   // 0 if disable, 1 if enable

/**********************
 *      TYPEDEFS
 **********************/
enum {
    HAL_WLAN_MSG_ID_SCAN_RESULT = 0,
    HAL_WLAN_MSG_ID_UI_STATE_CHG,
    HAL_WLAN_MSG_ID_DISCONNECT,
    HAL_WLAN_MSG_ID_STA_UP,
    HAL_WLAN_MSG_ID_STA_DOWN,
    HAL_WLAN_MSG_ID_ACT_AP_RSSI,
    HAL_WLAN_MSG_ID_LCD_WAKEUP,
    HAL_WLAN_MSG_ID_PERIODIC_SCAN,
    HAL_WLAN_MSG_ID_NETIF_CONFIG,
    HAL_WLAN_MSG_ID_GET_IP,
    HAL_WLAN_MSG_ID_SDIO_OPEN_SUCCESS,
    HAL_WLAN_MSG_ID_SDIO_OPEN_FAILED,

    /* from setting ui */
    HAL_WLAN_MSG_ID_OPEN_WLAN,
    HAL_WLAN_MSG_ID_RESET,
    HAL_WLAN_MSG_ID_CLOSE_WLAN,
    HAL_WLAN_MSG_ID_SCAN_AP,
    HAL_WLAN_MSG_ID_OPEN_AP,
    HAL_WLAN_MSG_ID_DEL_NW,
    HAL_WLAN_MSG_ID_SET_AUTO_SEL_NW,
    /* from setting ui */

    /* from bt */
    HAL_WLAN_MSG_ID_PROC_CONTINUE,
    HAL_WLAN_MSG_ID_HW_RESET_START,
    HAL_WLAN_MSG_ID_HW_RESET_END,
    /* from bt */

    /* from cilent app */
    HAL_WLAN_MSG_ID_OPEN_WLAN_WITHOUT_SECURITY,
    HAL_WLAN_MSG_ID_OPEN_NW_WITHOUT_SECURITY,
    HAL_WLAN_MSG_ID_DEL_NW_WITHOUT_SECURITY,
    /* from cilent app */
};
typedef uint8_t HAL_WLAN_MSG_ID_T;

typedef struct {
    HAL_WLAN_MSG_ID_T id;
    void *msg;
} hal_wlan_msg_t;

typedef struct {
    uint8_t state;          /* wlan will be opened if 1 and closed if 0 */
    uint8_t is_auto_sel_nw; /* select WLAN intelligently when WLAN connection is poor if 1 */
    uint8_t nw_num;
    hal_wlan_nw_t * nw;
} hal_wlan_nv_t;

enum {
    HAL_WLAN_WRITE_NV_MODE_RESET = 0,
    HAL_WLAN_WRITE_NV_MODE_REPLACE,
    HAL_WLAN_WRITE_NV_MODE_APPEND,
};
typedef uint8_t HAL_WLAN_WRITE_NV_MODE_T;

typedef struct {
    uint8_t ap_num;
    uint8_t hid_ap_num;
    hal_wlan_ap_t * ap;
    int8_t hid_ap_power[HAL_WLAN_SECURITY_MAX];
} hal_wlan_scan_result_t;

typedef struct {
    uint8_t max_periodic_timeout_count;
    bool event_noti_ind;
    bool periodic_scan_pending;
    bool disc_flag;         /* disconnect act ap,
                             * switch new ap or nw when an ap is opening */
    bool reset_flag;
    bool wait_bt_open_flag;
} hal_wlan_global_t;

typedef struct
{
    void * id;
    uint8_t timeout_count;
    bool is_running;
} hal_wlan_timer_t;

enum {
    HAL_WLAN_TIMER_ID_PERIOD_SCAN = 0,
    HAL_WLAN_TIMER_ID_GET_IP,
    HAL_WLAN_TIMER_ID_SCAN_PROTECT,
    HAL_WLAN_TIMER_ID_CHECK_SDIO_CFG,
    HAL_WLAN_MAX_TIMER_NUM
};

/**********************
 *  STATIC PROTOTYPES
 **********************/
static void hal_wlan_write_nv(uint32_t offset, uint32_t size, void * data,
                              HAL_WLAN_WRITE_NV_MODE_T mode);
static void hal_wlan_read_nv(hal_wlan_nv_t * nv, bool read_all);
static void hal_wlan_send_msg(HAL_WLAN_MSG_ID_T msg_id, void * data);
static bool hal_wlan_is_opened(const char * txt);
static void hal_wlan_del_nw_from_nv(hal_wlan_nw_t * nw);
static void hal_wlan_open_wlan(void);
static void hal_wlan_open_wlan_without_security(void);
static void hal_wlan_adp_main(void * para);
static void hal_wlan_timer_start(uint8_t timer_id);
static bool hal_wlan_timer_stop(uint8_t timer_id);

/**********************
 *  STATIC VARIABLES
 **********************/
static TASK_HANDLE * adp_task_id;
static bool is_in_wlan_ui;
static lv_ll_t nw_list;
static hal_wlan_info_t * wlan_info = NULL;
static hal_wlan_global_t * wlan_global = NULL;
static HAL_WLAN_EVENT_CB ui_event_cb = NULL;
static HAL_WLAN_GET_LCD_STATUS_CB lcd_status_cb = NULL;
static HAL_WLAN_GET_CM_CONN_SETTING_CB cm_conn_setting_cb = NULL;
#if USE_LV_BLUETOOTH != 0
static HAL_WLAN_OPEN_BT_WITHOUT_UI_CB open_bt_without_ui_cb = NULL;
#endif
static HAL_WLAN_HW_RESET_PHASE_T wlan_hw_reset = HAL_WLAN_HW_RESET_PHASE_NULL;
static hal_wlan_timer_t wlan_timer[HAL_WLAN_MAX_TIMER_NUM];

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 ***********************/
void hal_wlan_config(void)
{
#ifndef BUILD_IN_PC_SIMULATOR
    int32_t ret = 0;
    if(HERON_CHIP == GetWiFiType()) { // 5803
        if(PMIC_IS_PM813() || PMIC_IS_PM813S()) {
            printf("%s: 5803 heron wifi pm813\n", __FUNCTION__);
            ret = sdio_init(2, 32, 33, 79, 122, 1);
        } else if(PMIC_IS_PM803()) {
            printf("%s: 5803 heron wifi pm803\n", __FUNCTION__);
#if 0
            ret = sdio_init(2, 126, 33, 79, 124, 0);
#else
            /* use GPIO76 as host_wakeup_wifi instead of GPIO124 which is used as TP_RST for watch UI */
            ret = sdio_init(2, 126, 33, 79, 76, 0);
#endif
        } else {
            printf("%s: warning, 5803 heron wifi, but unknown pmic chip\n", __FUNCTION__);
            ret = -1;
        }
    } else { // 5505
        printf("%s: 5505 wifi\n", __FUNCTION__);
        ret = sdio_init(2, 83, 34, -1, -1, 1);
    }
    printf("%s: sdio_init, ret %d\n", __FUNCTION__, ret);
#endif
}

void hal_wlan_init(bool is_flight_mode, HAL_WLAN_GET_LCD_STATUS_CB status_cb,
                   HAL_WLAN_EVENT_CB event_cb)
{
    adp_task_id
        = uos_create_task(hal_wlan_adp_main, NULL, HAL_WLAN_ADP_TASK_MSGQSIZE,
                          HAL_WLAN_ADP_TASK_STACKSIZE, HAL_WLAN_ADP_TASK_PRIORITY, "wlan_adp");

#ifdef BUILD_IN_PC_SIMULATOR
    // reset nvm for test
    uint8_t nv[2] = {0, HAL_WLAN_DEFAULT_AUTO_SEL_NW};
    hal_wlan_write_nv(0, 2, nv, HAL_WLAN_WRITE_NV_MODE_RESET);
#endif

    lcd_status_cb = status_cb;
    ui_event_cb = event_cb;

    hal_wlan_nv_t nvm;
    hal_wlan_read_nv(&nvm, true);

    _lv_ll_init(&nw_list, sizeof(hal_wlan_nw_t));
    hal_wlan_nw_t * nw = NULL;
    for(uint32_t i = 0;i < nvm.nw_num;i++) {
        if('\0' != nvm.nw[i].ssid[0]) {
            nw = _lv_ll_ins_tail(&nw_list);
            Hal_Mem_Copy(nw, &nvm.nw[i], sizeof(hal_wlan_nw_t));
        }
    }
    if(nvm.nw) {
        Hal_Mem_Free(nvm.nw);
    }

    printf("%s: state %d, nw num %d\n", __FUNCTION__, nvm.state, nvm.nw_num);

    for(uint8_t i = 0;i < HAL_WLAN_MAX_TIMER_NUM;i++) {
        uos_timer_create(&wlan_timer[i].id);
        wlan_timer[i].timeout_count = 0;
        wlan_timer[i].is_running = false;
    }

    if(false == is_flight_mode) {
        if(1 == nvm.state) {
            hal_wlan_open_wlan();
        } else if(nw && (HAL_WLAN_SECURITY_UNSPECIFIED == nw->security)) {
            hal_wlan_open_wlan_without_security();
        }
    }
}

#if USE_LV_BLUETOOTH != 0
bool hal_wlan_delay_to_start_bt(HAL_WLAN_OPEN_BT_WITHOUT_UI_CB cb)
{
    if(wlan_info && (HAL_WLAN_STATE_INIT == wlan_info->state)) {
        printf("%s: buffer open bt req\n", __FUNCTION__);
        open_bt_without_ui_cb = cb;
        return true;
    }
    return false;
}
#endif

void hal_wlan_reset(void)
{
    printf("%s\n", __FUNCTION__);

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_RESET, NULL);
}

void hal_wlan_proc_continue(void)
{
    if(false == hal_wlan_is_opened(NULL)) {
        return;
    }

    if(!wlan_global->wait_bt_open_flag) {
        return;
    }

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_PROC_CONTINUE, NULL);
}

bool hal_wlan_hw_reset_start(void)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return false;
    }

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_HW_RESET_START, NULL);
    return true;
}

void hal_wlan_hw_reset_end(void)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return;
    }

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_HW_RESET_END, NULL);
}

bool hal_wlan_wait_for_reopen_for_hw_reset(void)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return false;
    }

    if(HAL_WLAN_HW_RESET_PHASE_CLOSE == wlan_hw_reset) {
        return true;
    }

    return false;
}

void hal_wlan_ui_open_flight_mode(void)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return;
    }

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_CLOSE_WLAN, NULL);
}

void hal_wlan_ui_close_flight_mode(void)
{
    hal_wlan_nv_t nvm;
    hal_wlan_read_nv(&nvm, false);
    if(1 == nvm.state) {
        printf("%s: reopen wlan upon the end of flight mode\n", __FUNCTION__);
        hal_wlan_open_wlan();
    } else {
        printf("%s: state 0\n", __FUNCTION__);
    }
}

bool hal_wlan_ui_open_wlan(void)
{
    if(hal_wlan_is_opened(__FUNCTION__)) {
        return false;
    }

    uint8_t state = 1;
    hal_wlan_write_nv(0, 1, &state, HAL_WLAN_WRITE_NV_MODE_REPLACE);

    hal_wlan_open_wlan();

    return true;
}

bool hal_wlan_ui_close_wlan(void)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return false;
    }

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_CLOSE_WLAN, NULL);

    return true;
}

bool hal_wlan_ui_scan_ap(void)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return false;
    }

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_SCAN_AP, NULL);

    return true;
}

bool hal_wlan_ui_open_ap(char * ssid, HAL_WLAN_SECURITY_T security, char * new_pwd)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return false;
    }

    if(NULL == ssid) {
        printf("%s: ssid is NULL\n", __FUNCTION__);
        return false;
    }

    if(HAL_WLAN_SECURITY_MAX <= security) {
        printf("%s: warning, invalid security %d\n", __FUNCTION__, security);
        return false;
    }

    if(new_pwd) {
        printf("%s: ssid %s, sec %d, pwd %s\n", __FUNCTION__, ssid, security, new_pwd);
    } else {
        printf("%s: ssid %s, sec %d\n", __FUNCTION__, ssid, security);
    }

    hal_wlan_nw_t * nw = Hal_Mem_Alloc(sizeof(hal_wlan_nw_t));
    Hal_Mem_Set(nw, 0, sizeof(hal_wlan_nw_t));
    Hal_Mem_Copy(nw->ssid, ssid, strlen(ssid));
    nw->security = security;
    if(new_pwd && (0 < strlen(new_pwd))) {
        Hal_Mem_Copy(nw->pwd, new_pwd, strlen(new_pwd));
    }
    hal_wlan_send_msg(HAL_WLAN_MSG_ID_OPEN_AP, nw);

    return true;
}

void hal_wlan_ui_state_chg(bool is_in_ui)
{
    printf("%s: is_in_ui new %d, old %d\n", __FUNCTION__, is_in_ui, is_in_wlan_ui);

    if(false == hal_wlan_is_opened(NULL)) {
        is_in_wlan_ui = is_in_ui;
        return;
    }

    if(HAL_WLAN_STATE_INIT == wlan_info->state) {
        printf("%s: HAL_WLAN_STATE_INIT\n", __FUNCTION__);
        is_in_wlan_ui = is_in_ui;
        return;
    }

    bool * ui_state = Hal_Mem_Alloc(sizeof(bool));
    *ui_state = is_in_ui;
    hal_wlan_send_msg(HAL_WLAN_MSG_ID_UI_STATE_CHG, ui_state);
}

bool hal_wlan_ui_del_saved_nw(char * ssid, HAL_WLAN_SECURITY_T security)
{
    if(NULL == ssid) {
        printf("%s: ssid is NULL\n", __FUNCTION__);
        return false;
    }

    if(HAL_WLAN_SECURITY_MAX <= security) {
        printf("%s: wrong security %d\n", __FUNCTION__, security);
        return false;
    }

    printf("%s: security %d, ssid %s\n", __FUNCTION__, security, ssid);

    if(hal_wlan_is_opened(__FUNCTION__)) {
        hal_wlan_nw_t * nw = Hal_Mem_Alloc(sizeof(hal_wlan_nw_t));
        Hal_Mem_Set(nw, 0, sizeof(hal_wlan_nw_t));
        Hal_Mem_Copy(nw->ssid, ssid, strlen(ssid));
        nw->security = security;
        hal_wlan_send_msg(HAL_WLAN_MSG_ID_DEL_NW, nw);
    } else {
        hal_wlan_nw_t * nw = _lv_ll_get_head(&nw_list);
        while(nw) {
            if((0 == strcmp(ssid, nw->ssid)) && (security == nw->security)) {
                break;
            }
            nw = _lv_ll_get_next(&nw_list, nw);
        }
        if(nw) {
            _lv_ll_remove(&nw_list, nw);
            hal_wlan_del_nw_from_nv(nw);
            Hal_Mem_Free(nw);
        } else {
            printf("%s: waring, not find the nw\n", __FUNCTION__);
            return false;
        }
    }

    return true;
}

bool hal_wlan_ui_add_nw(hal_wlan_nw_t * nw)
{
    if(NULL == nw) {
        printf("%s: nw is NULL\n", __FUNCTION__);
        return false;
    }
    if(HAL_WLAN_SECURITY_MAX <= nw->security) {
        printf("%s: wrong security %d\n", __FUNCTION__, nw->security);
        return false;
    }
    uint8_t pwd_len = strlen(nw->pwd);
    if(hal_wlan_get_min_pwd_len(nw->security) > pwd_len) {
        printf("%s: pwd %s is too short for security %d\n", __FUNCTION__, nw->pwd, nw->security);
        return false;
    }

    printf("%s: security %d, ssid %s, pwd %s\n", __FUNCTION__, nw->security, nw->ssid, nw->pwd);

    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return false;
    }

    hal_wlan_nw_t * saved_nw = Hal_Mem_Alloc(sizeof(hal_wlan_nw_t));
    Hal_Mem_Copy(saved_nw, nw, sizeof(hal_wlan_nw_t));
    if(HAL_WLAN_SECURITY_OPEN == nw->security) {
        Hal_Mem_Set(saved_nw->pwd, 0, HAL_WLAN_MAX_PWD_LEN + 1);
    }
    hal_wlan_send_msg(HAL_WLAN_MSG_ID_OPEN_AP, saved_nw);

    return true;
}

bool hal_wlan_ui_set_auto_sel_nw(bool is_auto)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return false;
    }

    printf("%s: is_auto %d\n", __FUNCTION__, is_auto);

    bool * auto_state = Hal_Mem_Alloc(sizeof(bool));
    *auto_state = is_auto;
    hal_wlan_send_msg(HAL_WLAN_MSG_ID_SET_AUTO_SEL_NW, auto_state);

    return true;
}

void hal_wlan_lcd_wakeup(bool onoff)
{
    if(false == hal_wlan_is_opened(NULL)) {
        return;
    }

    printf("%s: onoff %d\n", __FUNCTION__, onoff);

    if(HAL_WLAN_HW_RESET_PHASE_NULL == wlan_hw_reset) {
        wifi_lcdWakeup(onoff);
    }

    if(onoff) {
        hal_wlan_send_msg(HAL_WLAN_MSG_ID_LCD_WAKEUP, NULL);
    }
}

hal_wlan_info_t * hal_wlan_get_info(void)
{
    return wlan_info;
}

lv_ll_t * hal_wlan_get_nw_list(void)
{
    return &nw_list;
}

HAL_WLAN_SIGNAL_STRENGTH_T hal_wlan_rssi_level_calc(int8_t rssi)
{
    uint8_t level;
    if(0 <= rssi) {
        // invalid rssi
        level = HAL_WLAN_SIGNAL_STRENGTH_NO;
    } else if(HAL_WLAN_RSSI_MIN >= rssi) {
        level = HAL_WLAN_SIGNAL_STRENGTH_NO;
    } else if (HAL_WLAN_RSSI_MAX <= rssi) {
        level = HAL_WLAN_SIGNAL_STRENGTH_EXCELLENT;
    } else {
        level = (uint8_t)(((float)(rssi - HAL_WLAN_RSSI_MIN)) *
                          HAL_WLAN_SIGNAL_STRENGTH_GOOD / HAL_WLAN_RSSI_RANGE) + 1;
    }
    /* printf("%s: level %d, rssi %d\n", __FUNCTION__, level, rssi); */

    return level;
}

HAL_WLAN_SIGNAL_STRENGTH_T hal_wlan_get_rssi_level(void)
{
    if(wlan_info) {
        if(wlan_info->proc.ap
           && ((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.ap->state)
               || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.ap->state))) {
            return hal_wlan_rssi_level_calc(wlan_info->proc.ap->power);
        }
    }
    return HAL_WLAN_SIGNAL_STRENGTH_NO;
}

void hal_wlan_get_cm_conn_setting_cb_reg(HAL_WLAN_GET_CM_CONN_SETTING_CB cb)
{
    cm_conn_setting_cb = cb;
}

bool hal_wlan_is_connected_state(void)
{
    if(wlan_info
       && ((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.proc_state)
           || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.proc_state))) {
        return true;
    } else {
        return false;
    }
}

void hal_wlan_set_wifi_ind(hal_wlan_wifi_info_t * info)
{
    /* set wifi from client app other than wifi setting */

    if(NULL == info) {
        printf("%s: warning, info is NULL\n", __FUNCTION__);
        return;
    }

    printf("%s: cmd %d, ssid %s, pwd %s\n", __FUNCTION__, info->cmd, info->ssid, info->pwd);

    if(1 < info->cmd) {
        printf("%s: warning, unknown cmd\n", __FUNCTION__);
        return;
    }

    if(0 == strlen(info->ssid)) {
        printf("%s: no ssid\n", __FUNCTION__);
        return;
    }

    hal_wlan_nw_t * nw = Hal_Mem_Alloc(sizeof(hal_wlan_nw_t));
    nw->security = HAL_WLAN_SECURITY_UNSPECIFIED;
    Hal_Mem_Copy(nw->ssid, info->ssid, HAL_WLAN_MAX_SSID_LEN + 1);
    Hal_Mem_Copy(nw->pwd, info->pwd, HAL_WLAN_MAX_PWD_LEN + 1);

    if(1 == info->cmd) {
        if(false == hal_wlan_is_opened(__FUNCTION__)) {
            hal_wlan_open_wlan_without_security();
        }

        hal_wlan_send_msg(HAL_WLAN_MSG_ID_OPEN_NW_WITHOUT_SECURITY, nw);
    } else {
        hal_wlan_send_msg(HAL_WLAN_MSG_ID_DEL_NW_WITHOUT_SECURITY, nw);
    }
}

uint8_t hal_wlan_get_min_pwd_len(HAL_WLAN_SECURITY_T security)
{
    uint8_t len = 0;
    switch(security) {
    case HAL_WLAN_SECURITY_WEP:
        len = HAL_WLAN_MIN_WEP_PWD_LEN;
        break;
    case HAL_WLAN_SECURITY_WPA:
    case HAL_WLAN_SECURITY_WPA2:
    case HAL_WLAN_SECURITY_WPA_WPA2:
        len = HAL_WLAN_MIN_WPA_PWD_LEN;
        break;
    default:
        break;
    }

    return len;
}

/**********************
 *   STATIC FUNCTIONS
 ***********************/
static void hal_wlan_write_nv(uint32_t offset, uint32_t size, void * data,
                              HAL_WLAN_WRITE_NV_MODE_T mode)
{
    lv_fs_file_t file = {};
    if(HAL_WLAN_WRITE_NV_MODE_RESET == mode) {
        lv_fs_open(&file, HAL_WLAN_NVM_PATH, LV_FS_MODE_WR);
    } else if(HAL_WLAN_WRITE_NV_MODE_REPLACE == mode) {
        lv_fs_open(&file, HAL_WLAN_NVM_PATH, LV_FS_MODE_RD | LV_FS_MODE_APPEND);
        lv_fs_seek(&file, offset);
    } else {
        lv_fs_open(&file, HAL_WLAN_NVM_PATH, LV_FS_MODE_WR | LV_FS_MODE_APPEND);
    }
    lv_fs_write(&file, data, size, NULL);
    lv_fs_close(&file);
}

static void hal_wlan_read_nv(hal_wlan_nv_t * nv, bool read_all)
{
    if(NULL == nv) return;

    nv->state = 0;
    nv->is_auto_sel_nw = HAL_WLAN_DEFAULT_AUTO_SEL_NW;
    nv->nw_num = 0;
    nv->nw = NULL;

    lv_fs_file_t file = {};
    lv_fs_open(&file, HAL_WLAN_NVM_PATH, LV_FS_MODE_RD);
    if(NULL == file.file_d) {
        /* create nv file and set the default value */
        hal_wlan_write_nv(0, 2, nv, HAL_WLAN_WRITE_NV_MODE_RESET);
    } else {
        uint32_t size;
        lv_fs_size(&file, &size);
        if(2 > size) {
            printf("%s: warning, nv file error\n", __FUNCTION__);
            hal_wlan_write_nv(0, 2, nv, HAL_WLAN_WRITE_NV_MODE_RESET);
        } else {
            lv_fs_seek(&file, 0);
            lv_fs_read(&file, nv, 2, NULL); /* read state and is_auto_sel_nw */
            if(false == read_all) {
                lv_fs_close(&file);
                return;
            }

            if(2 < size) {
                size -= 2;
                nv->nw_num = size / sizeof(hal_wlan_nw_t);
                if(0 == nv->nw_num) {
                    printf("%s: warning, ap info error\n", __FUNCTION__);
                    /* create nv file and set the default value */
                    nv->state = 0;
                    nv->is_auto_sel_nw = 1;
                    hal_wlan_write_nv(0, 2, nv, HAL_WLAN_WRITE_NV_MODE_RESET);
                } else {
                    nv->nw = (hal_wlan_nw_t *)Hal_Mem_Alloc(size);
                    lv_fs_seek(&file, 2);
                    lv_fs_read(&file, nv->nw, size, NULL);
                }
            }
        }
    }
    lv_fs_close(&file);
}

static void hal_wlan_add_new_nw_to_nv(hal_wlan_nw_t * nw)
{
    hal_wlan_nv_t nvm;
    hal_wlan_read_nv(&nvm, true);
    uint32_t i = 0;
    for(;i < nvm.nw_num;i++) {
        if('\0' == nvm.nw[i].ssid[0]) {
            break;
        }
    }
    if(nvm.nw) {
        Hal_Mem_Free(nvm.nw);
    }

    if(nvm.nw_num > i) {
        hal_wlan_write_nv(2 + sizeof(hal_wlan_nw_t) * i,
                          sizeof(hal_wlan_nw_t), nw,
                          HAL_WLAN_WRITE_NV_MODE_REPLACE);
    } else {
        hal_wlan_write_nv(2 + sizeof(hal_wlan_nw_t) * i,
                          sizeof(hal_wlan_nw_t), nw,
                          HAL_WLAN_WRITE_NV_MODE_APPEND);
    }
}

static void hal_wlan_chg_pwd_to_nv(hal_wlan_nw_t * nw)
{
    hal_wlan_nv_t nvm;
    hal_wlan_read_nv(&nvm, true);
    for(uint32_t i = 0;i < nvm.nw_num;i++) {
        if(('\0' != nvm.nw[i].ssid[0])
           && (0 == strcmp(nvm.nw[i].ssid, nw->ssid))
           && (nvm.nw[i].security == nw->security)) {
            Hal_Mem_Set(nvm.nw[i].pwd, 0, HAL_WLAN_MAX_PWD_LEN + 1);
            strncpy(nvm.nw[i].pwd, nw->pwd, HAL_WLAN_MAX_PWD_LEN + 1);
            uint32_t offset = 2 + sizeof(hal_wlan_nw_t) * i
                + HAL_WLAN_MAX_SSID_LEN + 1;
            hal_wlan_write_nv(offset, HAL_WLAN_MAX_PWD_LEN + 1,
                              nvm.nw[i].pwd, HAL_WLAN_WRITE_NV_MODE_REPLACE);
            break;
        }
    }
}

static void hal_wlan_del_nw_from_nv(hal_wlan_nw_t * nw)
{
    hal_wlan_nv_t nvm;
    hal_wlan_read_nv(&nvm, true);
    for(uint32_t i = 0;i < nvm.nw_num;i++) {
        if((0 == strcmp(nvm.nw[i].ssid, nw->ssid))
           && (nvm.nw[i].security == nw->security)) {
            Hal_Mem_Set(&nvm.nw[i], 0, sizeof(hal_wlan_nw_t));
            uint32_t offset = 2 + sizeof(hal_wlan_nw_t) * i;
            hal_wlan_write_nv(offset, sizeof(hal_wlan_nw_t), &nvm.nw[i],
                              HAL_WLAN_WRITE_NV_MODE_REPLACE);
            break;
        }
    }
}

static bool hal_wlan_is_opened(const char * txt)
{
    if(wlan_info && wlan_global) {
        if(txt) {
            printf("%s: wlan has been opened\n", txt);
        }
        return true;
    }

    if(txt) {
        printf("%s: wlan is not opened\n", txt);
    }
    return false;
}

static bool hal_wlan_get_cm_conn_setting(void)
{
    bool ret = true;
    if(cm_conn_setting_cb) {
        ret = cm_conn_setting_cb();
    }
    printf("%s: ret %d\n", __FUNCTION__, ret);

    return ret;
}

static void hal_wlan_open_wlan(void)
{
    if(hal_wlan_is_opened(__FUNCTION__)) {
        return;
    }

    wlan_info = Hal_Mem_Alloc(sizeof(hal_wlan_info_t));
    Hal_Mem_Set(wlan_info, 0, sizeof(hal_wlan_info_t));
    wlan_global = Hal_Mem_Alloc(sizeof(hal_wlan_global_t));
    Hal_Mem_Set(wlan_global, 0, sizeof(hal_wlan_global_t));

    _lv_ll_init(&wlan_info->saved_ap_list, sizeof(hal_wlan_saved_ap_t));
    _lv_ll_init(&wlan_info->scan_list, sizeof(hal_wlan_ap_t));

    hal_wlan_nv_t nvm;
    hal_wlan_read_nv(&nvm, false);

    if(0 == nvm.is_auto_sel_nw) {
        wlan_info->is_auto_sel_nw = false;
    } else {
        if(1 != nvm.is_auto_sel_nw) {
            printf("%s: warning, invalid auto sel nw %d in nvm!", __FUNCTION__, nvm.is_auto_sel_nw);
        }
        wlan_info->is_auto_sel_nw = true; // default value
    }

    printf("%s: is_auto_sel_nw %d\n", __FUNCTION__, wlan_info->is_auto_sel_nw);

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_OPEN_WLAN, NULL);
}

static void hal_wlan_open_wlan_without_security(void)
{
    if(NULL == wlan_info) {
        wlan_info = Hal_Mem_Alloc(sizeof(hal_wlan_info_t));
        Hal_Mem_Set(wlan_info, 0, sizeof(hal_wlan_info_t));
        _lv_ll_init(&wlan_info->saved_ap_list, sizeof(hal_wlan_saved_ap_t));
        _lv_ll_init(&wlan_info->scan_list, sizeof(hal_wlan_ap_t));
        wlan_info->is_auto_sel_nw = true; // default value
    }
    if(NULL == wlan_global) {
        wlan_global = Hal_Mem_Alloc(sizeof(hal_wlan_global_t));
        Hal_Mem_Set(wlan_global, 0, sizeof(hal_wlan_global_t));
    }

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_OPEN_WLAN_WITHOUT_SECURITY, NULL);
}

static void hal_wlan_discard_msg(bool only_sta_msg)
{
#ifndef BUILD_IN_PC_SIMULATOR
    uint8_t msg_count = Hal_Get_Message_Count((TASK_ID)adp_task_id);
    for(uint8_t i = 0;i < msg_count;i++) {
        hal_wlan_msg_t * msg =
            (hal_wlan_msg_t *)Hal_Receive_Message((TASK_ID)adp_task_id, false);
        if(!msg) break;

        printf("%s: msg id %d\n", __FUNCTION__, msg->id);

        // not discard hw reset message
        if(HAL_WLAN_MSG_ID_STA_DOWN == msg->id) {
            wlan_sta_err_status_e * err_status = (wlan_sta_err_status_e *)msg->msg;
            if((WLAN_STA_MODE_CONN_RESET == *err_status) ||
               (WLAN_FW_NEED_HW_RESET == *err_status)) {
                Hal_Send_Message((TASK_ID)adp_task_id, msg);
                continue;
            }
        } else if(HAL_WLAN_MSG_ID_HW_RESET_START == msg->id) {
            Hal_Send_Message((TASK_ID)adp_task_id, msg);
            continue;
        }

        if(only_sta_msg) {
            switch(msg->id) {
            case HAL_WLAN_MSG_ID_STA_UP:
            case HAL_WLAN_MSG_ID_STA_DOWN:
                if(msg->msg) {
                    Hal_Mem_Free(msg->msg);
                }
                Hal_Mem_Free(msg);
                break;
            default:
                Hal_Send_Message((TASK_ID)adp_task_id, msg);
                break;
            }
        } else {
            if(msg->msg) {
                Hal_Mem_Free(msg->msg);
            }
            Hal_Mem_Free(msg);
        }
    }
#endif
}

static void hal_wlan_event_notification(HAL_WLAN_EVENT_T event)
{
    if(!wlan_global || !ui_event_cb) {
        return;
    }

    printf("%s: event %d, is_in_ui %d, reset_flag %d\n",
           __FUNCTION__, event, is_in_wlan_ui, wlan_global->reset_flag);

    if(!is_in_wlan_ui) {
        return;
    }

    if(wlan_global->reset_flag
       && (HAL_WLAN_EVENT_START_SCAN != event)
       && (HAL_WLAN_EVENT_STOP_SCAN_ABNORMAL != event)
       && (HAL_WLAN_EVENT_UPDATE_ACT_AP_RSSI != event)) {
        return;
    }

    if(lcd_status_cb && (false == lcd_status_cb())) {
        if(false == wlan_global->event_noti_ind) {
            wlan_global->event_noti_ind = true;
            ui_event_cb(HAL_WLAN_EVENT_UPDATE_AP_LIST);
        }
        return;
    }

    ui_event_cb(event);
}

static void hal_wlan_start_scan(void)
{
    if(HAL_WLAN_HW_RESET_PHASE_NULL != wlan_hw_reset) {
        return;
    }

    hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_PERIOD_SCAN);

    printf("%s: wlan_sta_start_scan start\n", __FUNCTION__);
    int32_t ret = wlan_sta_start_scan();
    printf("%s: wlan_sta_start_scan end, ret %d\n", __FUNCTION__, ret);

    if(0 > ret) {
        hal_wlan_send_msg(HAL_WLAN_MSG_ID_SCAN_RESULT, NULL);
    }
}

static hal_wlan_nw_t * hal_wlan_handle_buffered_msg(hal_wlan_nw_t * opening_nw)
{
#ifndef BUILD_IN_PC_SIMULATOR
    for(;;) {
        hal_wlan_msg_t * msg =
            (hal_wlan_msg_t *)Hal_Receive_Message((TASK_ID)adp_task_id, false);
        if(!msg) break;

        printf("%s: msg id %d\n", __FUNCTION__, msg->id);

        if(HAL_WLAN_MSG_ID_OPEN_NW_WITHOUT_SECURITY == msg->id) {
            hal_wlan_nw_t * spec_nw = (hal_wlan_nw_t *)msg->msg;
            printf("%s: open nw, %s\n", __FUNCTION__, spec_nw->ssid);
            hal_wlan_nw_t * nw = _lv_ll_get_head(&nw_list);
            while(nw) {
                if(0 == strcmp(nw->ssid, spec_nw->ssid)) {
                    break;
                }
                nw = _lv_ll_get_next(&nw_list, nw);
            }
            if(NULL == nw) {
                nw = _lv_ll_ins_tail(&nw_list);
                Hal_Mem_Copy(nw, spec_nw, sizeof(hal_wlan_nw_t));
                hal_wlan_add_new_nw_to_nv(nw);
                printf("%s: add new nw, %s\n", __FUNCTION__, nw->ssid);
            } else {
                if(0 != strcmp(nw->pwd, spec_nw->pwd)) {
                    printf("%s: pwd changed, old %s\n", __FUNCTION__, nw->pwd);
                    Hal_Mem_Copy(nw->pwd, spec_nw->pwd, HAL_WLAN_MAX_PWD_LEN + 1);
                    hal_wlan_chg_pwd_to_nv(nw);
                }
            }
            opening_nw = nw;
        } else if(HAL_WLAN_MSG_ID_DEL_NW_WITHOUT_SECURITY == msg->id) {
            hal_wlan_nw_t * del_nw = (hal_wlan_nw_t *)msg->msg;
            hal_wlan_nw_t * nw = _lv_ll_get_head(&nw_list);
            while(nw) {
                if(0 == strcmp(nw->ssid, del_nw->ssid)) {
                    break;
                }
                nw = _lv_ll_get_next(&nw_list, nw);
            }
            if(NULL == nw) {
                printf("%s: warning, not find nw\n", __FUNCTION__);
            } else {
                if(opening_nw == nw) {
                    opening_nw = NULL;
                }
                _lv_ll_remove(&nw_list, nw);
                hal_wlan_del_nw_from_nv(nw);
                Hal_Mem_Free(nw);
            }
        }

        if(msg->msg) {
            Hal_Mem_Free(msg->msg);
        }
        Hal_Mem_Free(msg);
    }

    return opening_nw;
#else
    return NULL;
#endif
}

static void hal_wlan_close_wlan(bool is_wifi_close)
{
    for(uint8_t i = 0;i < HAL_WLAN_MAX_TIMER_NUM;i++) {
        hal_wlan_timer_stop(i);
    }

    if(hal_wlan_get_cm_conn_setting()) {
        int32_t ret = CM_SetConnectionSwitch(true);
        printf("%s: switch to lte, ret %d\n", __FUNCTION__, ret);
    }

    _lv_ll_clear(&wlan_info->saved_ap_list);
    _lv_ll_clear(&wlan_info->scan_list);

    wlan_info->state = HAL_WLAN_STATE_DEINIT;
    wlan_info->next_state = HAL_WLAN_STATE_INIT;

    if(HAL_WLAN_HW_RESET_PHASE_CLOSE != wlan_hw_reset) {
        wlan_set_close_cause(1);
        int32_t ret = wlan_wifi_close();
        printf("%s: wlan_wifi_close, ret %d\n", __FUNCTION__, ret);

        sdio_wifi_close();
    } else {
#if USE_LV_BLUETOOTH != 0
        wlan_bt_recover_connection_fw_assert();
#endif
    }
    wlan_hw_reset = HAL_WLAN_HW_RESET_PHASE_NULL;

    hal_wlan_discard_msg(false);

    Hal_Mem_Free(wlan_info);
    wlan_info = NULL;

    if(is_wifi_close) {
        hal_wlan_event_notification(HAL_WLAN_EVENT_WLAN_CLOSED);
    } else {
        hal_wlan_event_notification(HAL_WLAN_EVENT_OPEN_WLAN_FAILURE);
    }

    Hal_Mem_Free(wlan_global);
    wlan_global = NULL;
}

static void hal_wlan_close_wlan_without_security(void)
{
    for(uint8_t i = 0;i < HAL_WLAN_MAX_TIMER_NUM;i++) {
        hal_wlan_timer_stop(i);
    }

    if(hal_wlan_get_cm_conn_setting()) {
        int32_t ret = CM_SetConnectionSwitch(true);
        printf("%s: switch to lte, ret %d\n", __FUNCTION__, ret);
    }

    _lv_ll_clear(&wlan_info->saved_ap_list);
    _lv_ll_clear(&wlan_info->scan_list);

    wlan_info->state = HAL_WLAN_STATE_DEINIT;
    wlan_info->next_state = HAL_WLAN_STATE_INIT;

    wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_SAVED;
    wlan_info->proc.ap = NULL;

    wlan_set_close_cause(1);
    printf("%s: wlan_wifi_close start\n", __FUNCTION__);
    int32_t ret = wlan_wifi_close();
    printf("%s: wlan_wifi_close, ret %d\n", __FUNCTION__, ret);

    sdio_wifi_close();

    wlan_info->opening_nw = hal_wlan_handle_buffered_msg(NULL);

    if(_lv_ll_get_head(&nw_list)) {
        printf("%s: reopen wlan\n", __FUNCTION__);
        hal_wlan_open_wlan_without_security();
        return;
    }

    Hal_Mem_Free(wlan_info);
    wlan_info = NULL;

    hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);

    Hal_Mem_Free(wlan_global);
    wlan_global = NULL;
}

static void hal_wlan_scan_cb(wlan_scan_result_t * result)
{
    /* if(result) { */
    /*     printf("%s: ap num %d\n", __FUNCTION__, result->ap_num); */
    /* } else { */
    /*     printf("%s: result is NULL\n", __FUNCTION__); */
    /* } */

    if(false == hal_wlan_is_opened(NULL)) {
        return;
    }

    hal_wlan_scan_result_t * scan_rlt = NULL;
    if(result) {
        scan_rlt = Hal_Mem_Alloc(sizeof(hal_wlan_scan_result_t));
        Hal_Mem_Set(scan_rlt, 0, sizeof(hal_wlan_scan_result_t));
        if(0 < result->ap_num) {
            scan_rlt->ap = (hal_wlan_ap_t *)Hal_Mem_Alloc(sizeof(hal_wlan_ap_t) * result->ap_num);
            uint8_t j;
            HAL_WLAN_SECURITY_T security;
            for(uint8_t i = 0;i < result->ap_num;i++) {
                switch(result->ap_list[i].security) {
                case WLAN_SECURITY_OPEN:
                    security = HAL_WLAN_SECURITY_OPEN;
                    break;
                case WLAN_SECURITY_WEP:
                    security = HAL_WLAN_SECURITY_WEP;
                    break;
                case WLAN_SECURITY_WPA:
                    security = HAL_WLAN_SECURITY_WPA;
                    break;
                case WLAN_SECURITY_WPA2:
                    security = HAL_WLAN_SECURITY_WPA2;
                    break;
                case WLAN_SECURITY_AUTO:
                    security = HAL_WLAN_SECURITY_WPA_WPA2;
                    break;
                default:
                    /* printf("%s: warning, unknown security %d\n", */
                    /*        __FUNCTION__, result->ap_list[i].security); */
                    security = HAL_WLAN_SECURITY_MAX;
                    break;
                }

                if(0 == strlen(result->ap_list[i].ssid)) {
                    if(0 == scan_rlt->hid_ap_power[security]) {
                        scan_rlt->hid_ap_power[security] = result->ap_list[i].rssi;
                        scan_rlt->hid_ap_num++;
                    } else if(result->ap_list[i].rssi > scan_rlt->hid_ap_power[security]) {
                        scan_rlt->hid_ap_power[security] = result->ap_list[i].rssi;
                    }
                    continue;
                }

                for(j = 0;j < scan_rlt->ap_num;j++) {
                    if((0 == strcmp(scan_rlt->ap[j].ssid, result->ap_list[i].ssid))
                       && (scan_rlt->ap[j].security == security)) {
                        // repeated ap
                        if(scan_rlt->ap[j].power < result->ap_list[i].rssi) {
                            scan_rlt->ap[j].power = result->ap_list[i].rssi;
                        }
                        break;
                    }
                }
                if(scan_rlt->ap_num != j) {
                    continue;
                }

                strncpy(scan_rlt->ap[scan_rlt->ap_num].ssid, result->ap_list[i].ssid,
                        HAL_WLAN_MAX_SSID_LEN + 1);
                scan_rlt->ap[scan_rlt->ap_num].security = security;
                scan_rlt->ap[scan_rlt->ap_num].power = result->ap_list[i].rssi;
                /* printf("%s: %d, %s, sec %d, rssi %d\n", __FUNCTION__, scan_rlt->ap_num, */
                /*        scan_rlt->ap[scan_rlt->ap_num].ssid, scan_rlt->ap[scan_rlt->ap_num].security, */
                /*        scan_rlt->ap[scan_rlt->ap_num].power); */
                scan_rlt->ap_num++;
            }
        }
    }

    /* if(scan_rlt) { */
    /*     printf("%s: hid ap num %d", __FUNCTION__, scan_rlt->hid_ap_num); */
    /*     for(uint8_t i = 0;i < HAL_WLAN_SECURITY_MAX;i++) { */
    /*         printf(", %d", scan_rlt->hid_ap_power[i]); */
    /*     } */
    /*     printf("\n"); */
    /* } */

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_SCAN_RESULT, (void *)scan_rlt);
}

static void hal_wlan_ap_state_chg_cb(wlan_wifi_event_e event)
{
    printf("%s: event %d\n", __FUNCTION__, event);

    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return;
    }

    if(EVENT_STATION_UP == event) {
        hal_wlan_send_msg(HAL_WLAN_MSG_ID_STA_UP, NULL);
    } else if(EVENT_STATION_DOWN == event) {
        wlan_sta_err_status_e * err_status = Hal_Mem_Alloc(sizeof(wlan_sta_err_status_e));
        *err_status = (wlan_sta_err_status_e)wlan_get_err_code(WLAN_STA);
        hal_wlan_send_msg(HAL_WLAN_MSG_ID_STA_DOWN, (void *)err_status);
    }
}

static void hal_wlan_act_ap_rssi_level_cb(char rssi_level, int rssi_signal)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return;
    }

    if(NULL == wlan_info->proc.ap) {
        printf("%s: warning, no proc ap\n", __FUNCTION__);
        return;
    }

    if(HAL_WLAN_RSSI_MIN >= rssi_signal) {
        printf("%s: warning, invalid signal %d\n", __FUNCTION__, rssi_signal);
        return;
    }

    if((HAL_WLAN_AP_STATE_GETTING_IP == wlan_info->proc.ap->state)
       && !wlan_timer[HAL_WLAN_TIMER_ID_GET_IP].is_running) {
        printf("%s: not handle during lwip config\n", __FUNCTION__);
        return;
    }

    printf("%s: rssi level %d, signal %d\n", __FUNCTION__, rssi_level, rssi_signal);

    int8_t * data = Hal_Mem_Alloc(sizeof(int8_t));
    *data = rssi_signal;
    hal_wlan_send_msg(HAL_WLAN_MSG_ID_ACT_AP_RSSI, (void *)data);
}

#ifndef BUILD_IN_PC_SIMULATOR
static void hal_wlan_periodic_scan_timeout_cb(uint32_t param)
{
    wlan_timer[HAL_WLAN_TIMER_ID_PERIOD_SCAN].timeout_count++;

    if(wlan_timer[HAL_WLAN_TIMER_ID_PERIOD_SCAN].timeout_count != wlan_global->max_periodic_timeout_count) {
        return;
    }

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_PERIODIC_SCAN, NULL);

    hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_PERIOD_SCAN);
}
#endif

static void hal_wlan_start_periodic_scan(void)
{
#ifndef BUILD_IN_PC_SIMULATOR
    if(wlan_timer[HAL_WLAN_TIMER_ID_PERIOD_SCAN].is_running) {
        printf("%s: periodic timer has been started\n", __FUNCTION__);
        return;
    }

    if((HAL_WLAN_STATE_SCAN == wlan_info->state)
       || (HAL_WLAN_STATE_SCAN == wlan_info->next_state)) {
        return;
    }

    if(is_in_wlan_ui && lcd_status_cb && lcd_status_cb()) {
        hal_wlan_timer_start(HAL_WLAN_TIMER_ID_PERIOD_SCAN);
        wlan_global->max_periodic_timeout_count = HAL_WLAN_RESCAN_INTERVAL;
        printf("%s: start periodic scan in ui when lcd on\n", __FUNCTION__);
    } else {
        if(NULL == _lv_ll_get_head(&nw_list)) {
            return;
        }

        if(wlan_info->proc.ap
           && ((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.ap->state)
               || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.ap->state))) {
            if(false == wlan_info->is_auto_sel_nw) {
                printf("%s: not auto sel nw\n", __FUNCTION__);
                return;
            }
        }

        hal_wlan_timer_start(HAL_WLAN_TIMER_ID_PERIOD_SCAN);
        if(HAL_WLAN_MIN_PERIODIC_SCAN_INTERVAL > wlan_global->max_periodic_timeout_count) {
            wlan_global->max_periodic_timeout_count = HAL_WLAN_MIN_PERIODIC_SCAN_INTERVAL;
        } else if(HAL_WLAN_MAX_PERIODIC_SCAN_INTERVAL > wlan_global->max_periodic_timeout_count) {
            wlan_global->max_periodic_timeout_count *= 2;
        }

        if(lcd_status_cb && (false == lcd_status_cb())) {
            printf("%s: start periodic scan %d when lcd off\n",
                   __FUNCTION__, wlan_global->max_periodic_timeout_count);
        } else {
            printf("%s: start periodic scan %d when out of wlan ui\n",
                   __FUNCTION__, wlan_global->max_periodic_timeout_count);
        }
    }
#endif
}

static bool hal_wlan_open_bt(void)
{
    bool ret = false;
#if USE_LV_BLUETOOTH != 0
    if(open_bt_without_ui_cb) {
        if(open_bt_without_ui_cb()) {
            printf("%s: open bt after wlan opened\n", __FUNCTION__);
            ret = true;
        }
        open_bt_without_ui_cb = NULL;
    }
#endif
    printf("%s: ret %d\n", __FUNCTION__, ret);
    return ret;
}

static void hal_wlan_open_process(void)
{
    wlan_scan_compeleted_cb_register(hal_wlan_scan_cb);
    wlan_stat_chg_cb_register(hal_wlan_ap_state_chg_cb);
    wlan_sta_rssi_cb_register(hal_wlan_act_ap_rssi_level_cb);

    hal_wlan_nw_t * nw = _lv_ll_get_head(&nw_list);
    while(nw) {
        hal_wlan_saved_ap_t * ap = _lv_ll_ins_tail(&wlan_info->saved_ap_list);
        Hal_Mem_Set(ap, 0, sizeof(hal_wlan_saved_ap_t));
        ap->nw = nw;
        nw = _lv_ll_get_next(&nw_list, nw);
    }

    wlan_info->state = HAL_WLAN_STATE_SCAN;
    if(hal_wlan_open_bt()) {
        wlan_global->wait_bt_open_flag = true;
    } else {
        hal_wlan_start_scan();
    }
    hal_wlan_event_notification(HAL_WLAN_EVENT_WLAN_OPENED);
}

#ifndef BUILD_IN_PC_SIMULATOR
static void hal_wlan_check_sdio_config_timeout_cb(uint32_t param)
{
    if(1 == GetWifiConfigFlag()) {
        hal_wlan_send_msg(HAL_WLAN_MSG_ID_SDIO_OPEN_SUCCESS, NULL);
        hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_CHECK_SDIO_CFG);
    } else {
        wlan_timer[HAL_WLAN_TIMER_ID_CHECK_SDIO_CFG].timeout_count++;
        if(HAL_WLAN_MAX_CHECK_SDIO_CONFIG_COUNT == wlan_timer[HAL_WLAN_TIMER_ID_CHECK_SDIO_CFG].timeout_count) {
            hal_wlan_send_msg(HAL_WLAN_MSG_ID_SDIO_OPEN_FAILED, NULL);
            hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_CHECK_SDIO_CFG);
        }
    }
}
#endif

static void hal_wlan_adp_open_wlan_msg(void)
{
    int32_t ret = sdio_wifi_open();
    printf("%s: sdio_wifi_open, ret %d\n", __FUNCTION__, ret);

    if(0 == ret) {
#ifndef BUILD_IN_PC_SIMULATOR
        if(1 != GetWifiConfigFlag()) {
            hal_wlan_timer_start(HAL_WLAN_TIMER_ID_CHECK_SDIO_CFG);
            return;
        }
#endif

        wlan_wifi_init_type_t init_info = {};
        init_info.wifi_mode = WLAN_STA;
        ret = wlan_wifi_open(&init_info);
        printf("%s: wlan_wifi_open, ret %d\n", __FUNCTION__, ret);

        if(0 == ret) {
            hal_wlan_open_process();
            return;
        }
    }

    hal_wlan_close_wlan(false);
    hal_wlan_open_bt();
}

static void hal_wlan_adp_close_wlan_msg(void)
{
    printf("%s: hw reset %d\n", __FUNCTION__, wlan_hw_reset);

    uint8_t state = 0;
    hal_wlan_write_nv(0, 1, &state, HAL_WLAN_WRITE_NV_MODE_REPLACE);
    hal_wlan_close_wlan(true);
}

static void hal_wlan_adp_reset_msg(void)
{
    /* reset the nv file */
    uint8_t nv[2] = {0, 1};
    hal_wlan_write_nv(0, 2, nv, HAL_WLAN_WRITE_NV_MODE_RESET);

    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return;
    }

    hal_wlan_close_wlan(true);
}

static void hal_wlan_adp_scan_ap_msg(void)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        hal_wlan_event_notification(HAL_WLAN_EVENT_STOP_SCAN_ABNORMAL);
        return;
    }

    printf("%s: wlan state %d:%d, disc_flag %d, hw reset %d\n",
           __FUNCTION__, wlan_info->state, wlan_info->next_state,
           wlan_global->disc_flag, wlan_hw_reset);

    if((HAL_WLAN_STATE_SCAN == wlan_info->state)
        || (HAL_WLAN_STATE_SCAN == wlan_info->next_state)) {
        printf("%s: scanning\n", __FUNCTION__);
        return;
    } else if(HAL_WLAN_HW_RESET_PHASE_NULL != wlan_hw_reset) {
        if(HAL_WLAN_STATE_ON == wlan_info->state) {
            wlan_info->state = HAL_WLAN_STATE_SCAN;
        } else {
            wlan_info->next_state = HAL_WLAN_STATE_SCAN;
        }
        return;
    }

    hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_PERIOD_SCAN);

    if((HAL_WLAN_STATE_OPEN_SPEC == wlan_info->state)
       || (HAL_WLAN_STATE_OPEN_AUTO == wlan_info->state)) {
        wlan_info->next_state = HAL_WLAN_STATE_SCAN;
    } else if(HAL_WLAN_STATE_ON == wlan_info->state) {
        wlan_info->state = HAL_WLAN_STATE_SCAN;
        hal_wlan_start_scan();
    }
    hal_wlan_event_notification(HAL_WLAN_EVENT_START_SCAN);
}

static void hal_wlan_adp_periodic_scan_msg(void)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return;
    }

    printf("%s: wlan state %d:%d, disc_flag %d\n",
           __FUNCTION__, wlan_info->state, wlan_info->next_state, wlan_global->disc_flag);

    if((HAL_WLAN_STATE_INIT == wlan_info->state)
       || (HAL_WLAN_STATE_DEINIT == wlan_info->state)
       || (HAL_WLAN_STATE_SCAN == wlan_info->state)
       || (HAL_WLAN_STATE_SCAN == wlan_info->next_state)) {
        return;
    }

    if(HAL_WLAN_STATE_ON == wlan_info->state) {
        wlan_info->state = HAL_WLAN_STATE_SCAN;
        hal_wlan_start_scan();
    } else if(HAL_WLAN_STATE_INIT == wlan_info->next_state) {
        wlan_info->next_state = HAL_WLAN_STATE_SCAN;
    } else {
        printf("%s: warning, can not perform to scan\n", __FUNCTION__);
        return;
    }
    hal_wlan_event_notification(HAL_WLAN_EVENT_START_SCAN);
}

static void hal_wlan_sort_saved_ap_by_power(hal_wlan_saved_ap_t * saved_ap)
{
    hal_wlan_saved_ap_t * ap = _lv_ll_get_head(&wlan_info->saved_ap_list);
    while(ap) {
        if(ap == saved_ap) {
            break;
        }

        if(0 == ap->power) {
            _lv_ll_move_before(&wlan_info->saved_ap_list, saved_ap, ap);
            break;
        }

        if(ap->power < saved_ap->power) {
            _lv_ll_move_before(&wlan_info->saved_ap_list, saved_ap, ap);
            break;
        }
        ap = _lv_ll_get_next(&wlan_info->saved_ap_list, ap);
    }
    if(NULL == ap) {
        printf("%s: warning, not find saved ap %s\n", __FUNCTION__, saved_ap->nw->ssid);
    }
}

static void hal_wlan_ins_ap_to_scan_list(char * ssid, HAL_WLAN_SECURITY_T security, int8_t power)
{
    if(0 == power) {
        printf("%s: warning, power is 0 for %s\n", __FUNCTION__, ssid);
        return;
    }

    hal_wlan_ap_t * ap  = _lv_ll_ins_tail(&wlan_info->scan_list);
    Hal_Mem_Copy(ap->ssid, ssid, HAL_WLAN_MAX_SSID_LEN + 1);
    ap->security = security;
    ap->power = power;
    hal_wlan_ap_t * prev = _lv_ll_get_prev(&wlan_info->scan_list, ap);
    hal_wlan_ap_t * node = NULL;
    while(prev) {
        if(prev->power < ap->power) {
            node = prev;
        } else {
            break;
        }
        prev = _lv_ll_get_prev(&wlan_info->scan_list, prev);
    }
    if(node) {
        _lv_ll_move_before(&wlan_info->scan_list, ap, node);
    }
}

static void hal_wlan_save_scan_result(hal_wlan_scan_result_t * result)
{
    if(NULL == result) return;

    _lv_ll_clear(&wlan_info->scan_list);

    int8_t act_ap_power = 0;
    bool act_ap_hid = false;
    if(wlan_info->proc.ap) {
        act_ap_power = wlan_info->proc.ap->power;
        act_ap_hid = wlan_info->proc.ap->is_hidden;
    }

    hal_wlan_saved_ap_t * saved_ap = _lv_ll_get_head(&wlan_info->saved_ap_list);
    while(saved_ap) {
        if(0 == saved_ap->power) {
            break;
        }

        saved_ap->power = 0;
        saved_ap->is_hidden = false;

        saved_ap = _lv_ll_get_next(&wlan_info->saved_ap_list, saved_ap);
    }

    for(uint8_t i = 0;i < result->ap_num;i++) {
        saved_ap = _lv_ll_get_head(&wlan_info->saved_ap_list);
        while(saved_ap) {
            if(0 == strcmp(saved_ap->nw->ssid, result->ap[i].ssid)) {
                HAL_WLAN_SECURITY_T security = saved_ap->nw->security;
                if(HAL_WLAN_SECURITY_UNSPECIFIED == security) {
                    security = saved_ap->alt_security;
                }
                if(result->ap[i].security == security) {
                    saved_ap->power = result->ap[i].power;
                    hal_wlan_sort_saved_ap_by_power(saved_ap);
                    break;
                }
            }
            saved_ap = _lv_ll_get_next(&wlan_info->saved_ap_list, saved_ap);
        }

        if(NULL == saved_ap) {
            hal_wlan_ins_ap_to_scan_list(result->ap[i].ssid, result->ap[i].security,
                                         result->ap[i].power);
        }
    }

    if(wlan_info->proc.ap && (0 == wlan_info->proc.ap->power)) {
        wlan_info->proc.ap->power = act_ap_power;
        wlan_info->proc.ap->is_hidden = act_ap_hid;
        if(0 != act_ap_power) {
            hal_wlan_sort_saved_ap_by_power(wlan_info->proc.ap);
        }
    }

    Hal_Mem_Copy(wlan_info->hid_ap_power, result->hid_ap_power, HAL_WLAN_SECURITY_MAX);

    if(0 < result->hid_ap_num) {
        for(uint8_t i = 0;i < HAL_WLAN_SECURITY_MAX;i++) {
            if(0 == result->hid_ap_power[i]) {
                continue;
            }

            saved_ap = _lv_ll_get_tail(&wlan_info->saved_ap_list);
            while(saved_ap) {
                if(0 != saved_ap->power) {
                    break;
                }

                HAL_WLAN_SECURITY_T security = saved_ap->nw->security;
                if(HAL_WLAN_SECURITY_UNSPECIFIED == security) {
                    security = saved_ap->alt_security;
                }
                if(i == security) {
                    saved_ap->power = result->hid_ap_power[i];
                    saved_ap->is_hidden = true;
                    hal_wlan_sort_saved_ap_by_power(saved_ap);
                }
                saved_ap = _lv_ll_get_prev(&wlan_info->saved_ap_list, saved_ap);
            }
        }
    }

    saved_ap = _lv_ll_get_tail(&wlan_info->saved_ap_list);
    while(saved_ap) {
        if(0 != saved_ap->power) {
            break;
        }

        saved_ap->is_hidden = false;
        saved_ap->state = HAL_WLAN_AP_STATE_SAVED;
        saved_ap = _lv_ll_get_prev(&wlan_info->saved_ap_list, saved_ap);
    }
}

static void hal_wlan_open_ap(hal_wlan_saved_ap_t * ap)
{
    HAL_WLAN_SECURITY_T security;
    if(HAL_WLAN_SECURITY_UNSPECIFIED == ap->nw->security) {
        printf("%s: unspecified, %s, sec %d, pwd %s\n",
               __FUNCTION__, ap->nw->ssid, ap->alt_security, ap->nw->pwd);
        security = ap->alt_security;
    } else {
        printf("%s: %s, sec %d, pwd %s, conn_num %d\n",
               __FUNCTION__, ap->nw->ssid, ap->nw->security, ap->nw->pwd, ap->conn_num);
        security = ap->nw->security;
    }

    if(wlan_info->last_disc_ap) {
        wlan_info->last_act_ap = wlan_info->last_disc_ap;
        wlan_info->last_disc_ap = NULL;
    }

    if(HAL_WLAN_HW_RESET_PHASE_NULL != wlan_hw_reset) {
        return;
    }

    wlan_wifi_init_type_t init_info = {};
    init_info.wifi_mode = WLAN_STA;
    switch(security) {
    case HAL_WLAN_SECURITY_OPEN:
        init_info.security = WLAN_SECURITY_OPEN;
        break;
    case HAL_WLAN_SECURITY_WEP:
        init_info.security = WLAN_SECURITY_WEP;
        break;
    case HAL_WLAN_SECURITY_WPA:
        init_info.security = WLAN_SECURITY_WPA;
        break;
    case HAL_WLAN_SECURITY_WPA2:
        init_info.security = WLAN_SECURITY_WPA2;
        break;
    case HAL_WLAN_SECURITY_WPA_WPA2:
        init_info.security = WLAN_SECURITY_AUTO;
        break;
    default:
        break;
    }

    init_info.ssid_len = strlen(ap->nw->ssid);
    Hal_Mem_Copy(init_info.ssid, ap->nw->ssid, init_info.ssid_len);

    if(HAL_WLAN_SECURITY_OPEN != security) {
        init_info.key_len = strlen(ap->nw->pwd);
        if(0 < init_info.key_len) {
            Hal_Mem_Copy(init_info.key, ap->nw->pwd, init_info.key_len);
        }
    }

    int32_t ret = wlan_sta_connect(&init_info);
    printf("%s: wlan_sta_connect end, ret %d\n", __FUNCTION__, ret);

    ap->pwd_err_num = 0;
    ap->try_num = 0;

    if(0 > ret) {
        wlan_sta_err_status_e * err_status = Hal_Mem_Alloc(sizeof(wlan_sta_err_status_e));
        *err_status = WLAN_STA_MODE_NO_AP_FOUND;
        hal_wlan_send_msg(HAL_WLAN_MSG_ID_STA_DOWN, (void *)err_status);
    }
}

static void hal_wlan_prepare_to_disconnect(void)
{
    wlan_global->disc_flag = true;

    hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_GET_IP);

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_DISCONNECT, NULL);
}

static void hal_wlan_auto_open_ap(void)
{
    printf("%s: wlan state %d, hw reset %d\n",
           __FUNCTION__, wlan_info->state, wlan_hw_reset);

    wlan_info->state = HAL_WLAN_STATE_ON;
    wlan_info->next_state = HAL_WLAN_STATE_INIT;

    if(HAL_WLAN_HW_RESET_PHASE_NULL != wlan_hw_reset) {
        return;
    }

    hal_wlan_saved_ap_t * saved_ap = _lv_ll_get_head(&wlan_info->saved_ap_list);
    if(NULL == saved_ap) {
        printf("%s: no saved ap\n", __FUNCTION__);
        return;
    }

    if(wlan_info->proc.ap
       && ((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.proc_state)
           || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.proc_state))) {
#if 1
        if(false == wlan_info->is_auto_sel_nw) {
            return;
        } else if(HAL_WLAN_SIGNAL_STRENGTH_FAIR <=
                  hal_wlan_rssi_level_calc(wlan_info->proc.ap->power)) {
            return;
        } else {
            printf("%s: act ap power %d is poor, is_auto_sel_nw %d\n",
                   __FUNCTION__, wlan_info->proc.ap->power, wlan_info->is_auto_sel_nw);

            hal_wlan_start_periodic_scan();
        }
#else
        return;
#endif
    }

    if(wlan_info->last_act_ap
       && (0 == wlan_info->last_act_ap->try_num)
       && (HAL_WLAN_MAX_CONN_NUM > wlan_info->last_act_ap->conn_num)
       && (HAL_WLAN_SIGNAL_STRENGTH_FAIR <=
           hal_wlan_rssi_level_calc(wlan_info->last_act_ap->power))) {
        // priority to open last act ap
        hal_wlan_saved_ap_t * act_ap = wlan_info->proc.ap;
        wlan_info->proc.ap = wlan_info->last_act_ap;
        wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_OPENING;
        wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_OPENING;
        wlan_info->state = HAL_WLAN_STATE_OPEN_AUTO;
        printf("%s: flag %d, open last act ap, hid %d, %s\n", __FUNCTION__, wlan_global->disc_flag,
               wlan_info->proc.ap->is_hidden, wlan_info->proc.ap->nw->ssid);
        if(act_ap) {
            wlan_info->last_act_ap = act_ap;
            act_ap->state = HAL_WLAN_AP_STATE_SAVED;
            hal_wlan_prepare_to_disconnect();
        } else {
            hal_wlan_open_ap(wlan_info->proc.ap);
        }
        if(wlan_info->last_disc_ap) {
            wlan_info->last_act_ap = wlan_info->last_disc_ap;
            wlan_info->last_disc_ap = NULL;
        }
        return;
    }

    if(wlan_info->last_disc_ap) {
        wlan_info->last_act_ap = wlan_info->last_disc_ap;
        wlan_info->last_disc_ap = NULL;
    }

    while(saved_ap) {
        if(0 == saved_ap->power) {
            printf("%s: not find ap\n", __FUNCTION__);
            return;
        }

        if((HAL_WLAN_MAX_CONN_NUM > saved_ap->conn_num) &&
           (0 == saved_ap->try_num) &&
           (!wlan_info->proc.ap ||
            !wlan_info->proc.ap->is_hidden)) {
            break;
        }
        saved_ap = _lv_ll_get_next(&wlan_info->saved_ap_list, saved_ap);
    }
    if(NULL == saved_ap) {
        printf("%s: no ap to open\n", __FUNCTION__);
        saved_ap = _lv_ll_get_head(&wlan_info->saved_ap_list);
        while(saved_ap) {
            if(0 == saved_ap->power) {
                return;
            }

            saved_ap->try_num = 0;
            saved_ap = _lv_ll_get_next(&wlan_info->saved_ap_list, saved_ap);
        }
        return;
    }

    if(wlan_info->proc.ap
       && (HAL_WLAN_SIGNAL_STRENGTH_GOOD > hal_wlan_rssi_level_calc(saved_ap->power))) {
        printf("%s: no suitable ap to open\n", __FUNCTION__);
        return;
    }

    printf("%s: open new ap, state %d, %s\n", __FUNCTION__, saved_ap->state, saved_ap->nw->ssid);
    if(wlan_info->proc.ap) {
        wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_SAVED;
        wlan_info->last_act_ap = wlan_info->proc.ap;
        hal_wlan_prepare_to_disconnect();
    }
    wlan_info->proc.ap = saved_ap;
    wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_OPENING;
    if(HAL_WLAN_AP_STATE_RETRY != saved_ap->state) {
        wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_OPENING;
    }
    wlan_info->state = HAL_WLAN_STATE_OPEN_AUTO;
    if(false == wlan_global->disc_flag) {
        hal_wlan_open_ap(saved_ap);
    }
}

static void hal_wlan_auto_open_nw(void)
{
    if(NULL == wlan_info->opening_nw) {
        printf("%s: warning, no opening_nw\n", __FUNCTION__);
        return;
    }

    hal_wlan_saved_ap_t * saved_ap = _lv_ll_get_head(&wlan_info->saved_ap_list);
    if(NULL == saved_ap) {
        printf("%s: warning, no saved ap\n", __FUNCTION__);
        wlan_info->opening_nw = NULL;
        return;
    }

    while(saved_ap) {
        if(0 == saved_ap->power) {
            printf("%s: not find ap\n", __FUNCTION__);
            break;
        }

        if(HAL_WLAN_MAX_CONN_NUM > saved_ap->conn_num) {
            break;
        }
        saved_ap = _lv_ll_get_next(&wlan_info->saved_ap_list, saved_ap);
    }
    if((NULL == saved_ap) || (saved_ap && (0 == saved_ap->power))) {
        printf("%s: no ap to open\n", __FUNCTION__);
        wlan_info->opening_nw = NULL;

        if(HAL_WLAN_STATE_SCAN == wlan_info->next_state) {
            wlan_info->next_state = HAL_WLAN_STATE_INIT;
            wlan_info->state = HAL_WLAN_STATE_SCAN;
            hal_wlan_start_scan();
        } else {
            hal_wlan_auto_open_ap();
        }
        return;
    }

    wlan_info->proc.ap = saved_ap;
    wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_OPENING;
    wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_OPENING;
    hal_wlan_open_ap(saved_ap);
}

static void hal_wlan_adp_scan_result_msg(void * msg)
{
    printf("%s: state %d, %d, ui state %d, disc flag %d\n", __FUNCTION__, wlan_info->state,
           wlan_info->next_state, is_in_wlan_ui, wlan_global->disc_flag);

    if(HAL_WLAN_STATE_SCAN != wlan_info->state) {
        printf("%s: warning, non scan state\n", __FUNCTION__);
        return;
    }

    hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_SCAN_PROTECT);

    hal_wlan_scan_result_t * result = (hal_wlan_scan_result_t *)msg;

    hal_wlan_save_scan_result(result);

    if(wlan_global->disc_flag) {
        if(HAL_WLAN_STATE_OPEN_SPEC == wlan_info->next_state) {
            wlan_info->state = HAL_WLAN_STATE_OPEN_SPEC;
            wlan_info->next_state = HAL_WLAN_STATE_INIT;
        } else {
            wlan_info->state = HAL_WLAN_STATE_ON;
        }
    } else if(HAL_WLAN_STATE_OPEN_SPEC == wlan_info->next_state) {
        wlan_info->state = HAL_WLAN_STATE_OPEN_SPEC;
        wlan_info->next_state = HAL_WLAN_STATE_INIT;
        hal_wlan_open_ap(wlan_info->proc.ap);
    } else if(HAL_WLAN_STATE_OPEN_NW_WITHOUT_SECURITY == wlan_info->next_state) {
        wlan_info->next_state = HAL_WLAN_STATE_INIT;
        wlan_info->state = HAL_WLAN_STATE_OPEN_NW_WITHOUT_SECURITY;
        hal_wlan_auto_open_nw();
    } else if(HAL_WLAN_STATE_INIT == wlan_info->next_state) {
        hal_wlan_auto_open_ap();
    } else {
        printf("%s: warning, wrong state\n", __FUNCTION__);
    }

    hal_wlan_start_periodic_scan();

    if(NULL == result) {
        hal_wlan_event_notification(HAL_WLAN_EVENT_STOP_SCAN_ABNORMAL);
    } else {
        hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
    }

    if(result) {
        if((0 < result->ap_num) && result->ap) {
            Hal_Mem_Free(result->ap);
        }
    }
}

static void hal_wlan_disc_opening_process(void)
{
    if(HAL_WLAN_HW_RESET_PHASE_NULL != wlan_hw_reset) {
        return;
    }

    wlan_set_close_cause(0);
    int32_t ret = wlan_wifi_close();
    printf("%s: wlan_wifi_close, ret %d\n", __FUNCTION__, ret);
    hal_wlan_discard_msg(true);
    wlan_wifi_init_type_t init_info = {};
    init_info.wifi_mode = WLAN_STA;
    ret = wlan_wifi_open(&init_info);
    printf("%s: wlan_wifi_open, ret %d\n", __FUNCTION__, ret);
}

static void hal_wlan_adp_open_ap_msg(void * data)
{
    if(NULL == data) {
        printf("%s: warning, data is NULL\n", __FUNCTION__);
        return;
    }

    printf("%s: state %d:%d, disc %d, reset %d, hw reset %d\n",
           __FUNCTION__, wlan_info->state, wlan_info->next_state,
           wlan_global->disc_flag, wlan_global->reset_flag, wlan_hw_reset);

    hal_wlan_nw_t * nw = (hal_wlan_nw_t *)data;

    hal_wlan_saved_ap_t * spec_saved_ap = _lv_ll_get_head(&wlan_info->saved_ap_list);
    bool is_new_nw = false;
    bool is_pwd_changed = false;
    while(spec_saved_ap) {
        if((0 == strcmp(spec_saved_ap->nw->ssid, nw->ssid))
           && (spec_saved_ap->nw->security == nw->security)) {
            if((HAL_WLAN_SECURITY_OPEN != nw->security)
               && (0 < strlen(nw->pwd))
               && (0 != strcmp(spec_saved_ap->nw->pwd, nw->pwd))) {
                printf("%s: password changed, old %s\n", __FUNCTION__, spec_saved_ap->nw->pwd);
                is_pwd_changed = true;
                Hal_Mem_Copy(spec_saved_ap->nw->pwd, nw->pwd, HAL_WLAN_MAX_PWD_LEN + 1);
                hal_wlan_chg_pwd_to_nv(spec_saved_ap->nw);
            }
            break;
        }
        spec_saved_ap = _lv_ll_get_next(&wlan_info->saved_ap_list, spec_saved_ap);
    }

    if(NULL == spec_saved_ap) {
        if((HAL_WLAN_SECURITY_OPEN != nw->security)
           && (0 == strlen(nw->pwd))) {
            printf("%s: warning, password is absent for security %d\n", __FUNCTION__, nw->security);
            return;
        }

        printf("%s: add new nw\n", __FUNCTION__);
        is_new_nw = true;

        spec_saved_ap = _lv_ll_ins_tail(&wlan_info->saved_ap_list);
        Hal_Mem_Set(spec_saved_ap, 0, sizeof(hal_wlan_saved_ap_t));

        spec_saved_ap->nw = _lv_ll_ins_tail(&nw_list);
        Hal_Mem_Copy(spec_saved_ap->nw, nw, sizeof(hal_wlan_nw_t));
        hal_wlan_add_new_nw_to_nv(spec_saved_ap->nw);

        if(NULL == _lv_ll_get_prev(&nw_list, spec_saved_ap->nw)) {
            hal_wlan_start_periodic_scan();
        }
    }

    if(is_new_nw) {
        hal_wlan_ap_t * scan_ap = _lv_ll_get_head(&wlan_info->scan_list);
        while(scan_ap) {
            if((0 == strcmp(scan_ap->ssid, spec_saved_ap->nw->ssid))
               && (scan_ap->security == spec_saved_ap->nw->security)) {
                break;
            }
            scan_ap = _lv_ll_get_next(&wlan_info->scan_list, scan_ap);
        }
        if(scan_ap) {
            spec_saved_ap->power = scan_ap->power;
            hal_wlan_sort_saved_ap_by_power(spec_saved_ap);

            _lv_ll_remove(&wlan_info->scan_list, scan_ap);
            Hal_Mem_Free(scan_ap);
        } else if(0 != wlan_info->hid_ap_power[spec_saved_ap->nw->security]) {
            printf("%s: find hidden ap\n", __FUNCTION__);
            spec_saved_ap->power = wlan_info->hid_ap_power[spec_saved_ap->nw->security];
            spec_saved_ap->is_hidden = true;
            hal_wlan_sort_saved_ap_by_power(spec_saved_ap);
        } else {
            printf("%s: not find ap\n", __FUNCTION__);
            return;
        }
    } else if(wlan_info->proc.ap
              && (false == is_pwd_changed)
              && (wlan_info->proc.ap->nw == spec_saved_ap->nw)) {
        printf("%s: open an act or opening ap, state %d\n",
               __FUNCTION__, wlan_info->proc.proc_state);
        if(HAL_WLAN_STATE_OPEN_AUTO == wlan_info->state) {
            wlan_info->state = HAL_WLAN_STATE_OPEN_SPEC;
            wlan_info->proc.ap->conn_num = 0;
            if(HAL_WLAN_AP_STATE_GETTING_IP == wlan_info->proc.proc_state) {
                wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_GETTING_IP;
            } else {
                wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_OPENING;
                hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
            }
        }
        return;
    }

    if(wlan_global->reset_flag) {
        wlan_global->reset_flag = false;
    }

    bool is_act = false;
    bool is_connected = false;
    bool is_opening = false;
    hal_wlan_saved_ap_t * old_ap = wlan_info->proc.ap;
    if(old_ap) {
        if((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.proc_state)
           || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.proc_state)
           || (HAL_WLAN_AP_STATE_GETTING_IP == wlan_info->proc.proc_state)) {
            is_act = true;
            if((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.proc_state)
               || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.proc_state)) {
                is_connected = true;
            }
        } else if(HAL_WLAN_AP_STATE_OPENING == wlan_info->proc.proc_state) {
            is_opening = true;
        }
    }

    spec_saved_ap->state = HAL_WLAN_AP_STATE_OPENING;
    wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_OPENING;
    wlan_info->proc.ap = spec_saved_ap;
    wlan_info->proc.is_first = true;
    wlan_info->proc.ap->conn_num = 0;

    if(is_act) {
        if(is_connected && (old_ap != spec_saved_ap)) {
            wlan_info->last_act_ap = old_ap;
            wlan_info->last_act_ap->state = HAL_WLAN_AP_STATE_SAVED;
        }
        old_ap->try_num = 0;
        hal_wlan_prepare_to_disconnect();
        if(HAL_WLAN_STATE_SCAN == wlan_info->state) {
            /* wait for scanning result */
            wlan_info->next_state = HAL_WLAN_STATE_OPEN_SPEC;
        } else {
            /* wait for station down */
            wlan_info->state = HAL_WLAN_STATE_OPEN_SPEC;
        }
    } else if(is_opening) {
        if(old_ap != spec_saved_ap) {
            if(HAL_WLAN_AP_STATE_OPENING == old_ap->state) {
                old_ap->state = HAL_WLAN_AP_STATE_SAVED;
                old_ap->try_num = 0;
                old_ap->pwd_err_num = 0;
            }
        }
        if(HAL_WLAN_STATE_SCAN == wlan_info->state) {
            /* wait for scanning result */
            wlan_info->next_state = HAL_WLAN_STATE_OPEN_SPEC;
        } else {
            if(HAL_WLAN_STATE_SCAN == wlan_info->next_state) {
                hal_wlan_start_periodic_scan();
            }
            wlan_info->state = HAL_WLAN_STATE_OPEN_SPEC;
            if(false == wlan_global->disc_flag) {
                hal_wlan_open_ap(spec_saved_ap);
                if(HAL_WLAN_HW_RESET_PHASE_NULL == wlan_hw_reset) {
                    /* discard station down caused by the connecting process interrupted */
                    hal_wlan_discard_msg(true);
                }
            }
        }
    } else if(HAL_WLAN_STATE_SCAN == wlan_info->state) {
        /* wait for scanning result */
        wlan_info->next_state = HAL_WLAN_STATE_OPEN_SPEC;
    } else {
        wlan_info->state = HAL_WLAN_STATE_OPEN_SPEC;
        hal_wlan_open_ap(spec_saved_ap);
    }

    hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
}

static void hal_wlan_adp_ui_state_chg_msg(void * data)
{
    bool is_in_ui = *((bool *)data);

    if(is_in_ui == is_in_wlan_ui) {
        printf("%s: not change\n", __FUNCTION__);
        return;
    }

    printf("%s: ui state old %d, new %d, wlan state %d:%d, hw reset %d\n",
           __FUNCTION__, is_in_wlan_ui, is_in_ui, wlan_info->state,
           wlan_info->next_state, wlan_hw_reset);

    is_in_wlan_ui = is_in_ui;

    if(false == is_in_wlan_ui) {
        return;
    }

    if(HAL_WLAN_HW_RESET_PHASE_NULL != wlan_hw_reset) {
        return;
    }

    wlan_global->max_periodic_timeout_count = HAL_WLAN_RESCAN_INTERVAL;

    if((HAL_WLAN_STATE_SCAN == wlan_info->state)
       || (HAL_WLAN_STATE_SCAN == wlan_info->next_state)) {
        return;
    }

    if(wlan_timer[HAL_WLAN_TIMER_ID_PERIOD_SCAN].is_running) {
        if(HAL_WLAN_RESCAN_INTERVAL > wlan_timer[HAL_WLAN_TIMER_ID_PERIOD_SCAN].timeout_count) {
            return;
        }

        hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_PERIOD_SCAN);
    }

    if(HAL_WLAN_STATE_ON != wlan_info->state) {
        wlan_info->next_state = HAL_WLAN_STATE_SCAN;
    } else {
        wlan_info->state = HAL_WLAN_STATE_SCAN;
        if(false == wlan_global->disc_flag) {
            hal_wlan_start_scan();
        }
    }
    hal_wlan_event_notification(HAL_WLAN_EVENT_START_SCAN);
}

static void hal_wlan_adp_del_nw_msg(void * data)
{
    if(NULL == data) {
        printf("%s: data is NULL\n", __FUNCTION__);
        return;
    }

    hal_wlan_nw_t * del_nw = (hal_wlan_nw_t *)data;

    printf("%s: state %d:%d, hw reset %d, disc %d, reset %d, sec %d, ssid %s\n",
           __FUNCTION__, wlan_info->state, wlan_info->next_state, wlan_hw_reset,
           wlan_global->disc_flag, wlan_global->reset_flag, del_nw->security, del_nw->ssid);

    hal_wlan_saved_ap_t * saved_ap = _lv_ll_get_head(&wlan_info->saved_ap_list);
    while(saved_ap) {
        if((0 == strcmp(saved_ap->nw->ssid, del_nw->ssid))
           && (saved_ap->nw->security == del_nw->security)) {
            break;
        }
        saved_ap = _lv_ll_get_next(&wlan_info->saved_ap_list, saved_ap);
    }
    if(NULL == saved_ap) {
        printf("%s: warning, not find the nw\n", __FUNCTION__);
        return;
    }

    _lv_ll_remove(&wlan_info->saved_ap_list, saved_ap);
    _lv_ll_remove(&nw_list, saved_ap->nw);
    hal_wlan_del_nw_from_nv(saved_ap->nw);

    if(saved_ap == wlan_info->last_disc_ap) {
        wlan_info->last_disc_ap = NULL;
    }
    if(saved_ap == wlan_info->last_act_ap) {
        wlan_info->last_act_ap = NULL;
    }

    if((false == saved_ap->is_hidden) && (0 != saved_ap->power)) {
        hal_wlan_ins_ap_to_scan_list(saved_ap->nw->ssid, saved_ap->nw->security, saved_ap->power);
    }

    Hal_Mem_Free(saved_ap->nw);
    Hal_Mem_Free(saved_ap);

    bool is_act = false;
    bool is_opening = false;
    if(wlan_info->proc.ap == saved_ap) {
        if((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.proc_state)
           || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.proc_state)
           || (HAL_WLAN_AP_STATE_GETTING_IP == wlan_info->proc.proc_state)) {
            is_act = true;
        } else if(HAL_WLAN_AP_STATE_OPENING == wlan_info->proc.proc_state) {
            is_opening = true;
        }
        wlan_info->proc.ap = NULL;
        if(HAL_WLAN_AP_STATE_GETTING_IP != wlan_info->proc.proc_state) {
            wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_SAVED;
        }
        if(wlan_global->reset_flag) {
            wlan_global->reset_flag = false;
        }
    }

    if(is_act) {
        printf("%s: disconnect act ap\n", __FUNCTION__);
        hal_wlan_prepare_to_disconnect();
    } else if(is_opening) {
        if(HAL_WLAN_STATE_SCAN == wlan_info->state) {
            wlan_info->next_state = HAL_WLAN_STATE_INIT;
        } else {
            if(false == wlan_global->disc_flag) {
                hal_wlan_disc_opening_process();
            }
            if(HAL_WLAN_STATE_SCAN == wlan_info->next_state) {
                wlan_info->state = HAL_WLAN_STATE_SCAN;
                wlan_info->next_state = HAL_WLAN_STATE_INIT;
                if(false == wlan_global->disc_flag) {
                    hal_wlan_start_scan();
                }
            } else if (wlan_global->disc_flag) {
                wlan_info->state = HAL_WLAN_STATE_ON;
            } else {
                hal_wlan_auto_open_ap();
            }
        }
    }

    hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
}

static void hal_wlan_adp_set_auto_sel_nw_msg(void * data)
{
    bool is_auto = *((bool *)data);

    printf("%s: is auto %d\n", __FUNCTION__, is_auto);

    wlan_info->is_auto_sel_nw = is_auto;

    uint8_t nv = (uint8_t)is_auto;
    hal_wlan_write_nv(1, 1, &nv, HAL_WLAN_WRITE_NV_MODE_REPLACE);

    if(is_auto &&(HAL_WLAN_STATE_ON == wlan_info->state)) {
        hal_wlan_auto_open_ap();

        if(HAL_WLAN_STATE_ON != wlan_info->state) {
            hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
        }
    }
}

#ifndef BUILD_IN_PC_SIMULATOR
static void hal_wlan_scan_protect_timeout_cb(uint32_t param)
{
    hal_wlan_scan_cb(NULL);
    hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_SCAN_PROTECT);
}
#endif

static void hal_wlan_adp_disconnect_msg(void * data)
{
    if(hal_wlan_get_cm_conn_setting()) {
        int32_t ret = CM_SetConnectionSwitch(true);
        printf("%s: switch to lte, ret %d\n", __FUNCTION__, ret);
    }

    printf("%s: wlan_sta_disconnect start\n", __FUNCTION__);
    int32_t ret = wlan_sta_disconnect((uint8_t *)data);
    printf("%s: wlan_sta_disconnect end, ret %d\n", __FUNCTION__, ret);

    if(0 > ret) {
        // disconnect conflict from user and lower
        wlan_sta_err_status_e * err_status = Hal_Mem_Alloc(sizeof(wlan_sta_err_status_e));
        *err_status = WLAN_STA_MODE_CONN_RETRY_MAX;
        hal_wlan_send_msg(HAL_WLAN_MSG_ID_STA_DOWN, (void *)err_status);
    }

#ifndef BUILD_IN_PC_SIMULATOR
    if(HAL_WLAN_STATE_SCAN == wlan_info->state) {
        hal_wlan_timer_start(HAL_WLAN_TIMER_ID_SCAN_PROTECT);
    }
#endif
}

static void hal_wlan_lwip_config_cb(uint32_t param)
{
    char * ifname = (char *)lwip_get_netif_uap_ifname();
    int32_t ret = lwip_iflist(ifname, "ip", wlan_info->ip);

    wlan_timer[HAL_WLAN_TIMER_ID_GET_IP].timeout_count++;

    if(0 != ret) {
        if(HAL_WLAN_GET_IP_MAX_TIMEOUT_COUNT == wlan_timer[HAL_WLAN_TIMER_ID_GET_IP].timeout_count) {
            hal_wlan_prepare_to_disconnect();
        }
        return;
    }

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_GET_IP, NULL);

    hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_GET_IP);
}

#ifdef BUILD_IN_PC_SIMULATOR
static void hal_wlan_getting_ip_task_cb(lv_task_t * task)
{
    hal_wlan_lwip_config_cb(0);
}
#endif

static void hal_wlan_adp_sta_up_msg(void)
{
    if(wlan_global->disc_flag) {
        printf("%s: rcv sta up during disc process\n", __FUNCTION__);
        return;
    }

    if(wlan_timer[HAL_WLAN_TIMER_ID_GET_IP].is_running) {
        printf("%s: wait for the complete of lwip configuration\n", __FUNCTION__);
        return;
    }

    if(NULL == wlan_info->proc.ap) {
        printf("%s: warning, no opening ap\n", __FUNCTION__);
        return;
    }

    if(HAL_WLAN_AP_STATE_OPENING != wlan_info->proc.proc_state) {
        printf("%s: warning, no opening ap, state %d, %s\n",
               __FUNCTION__, wlan_info->proc.proc_state, wlan_info->proc.ap->nw->ssid);
        return;
    }

    printf("%s: state %d:%d, disc flag %d, is_hid %d, ssid %s\n",
           __FUNCTION__, wlan_info->state, wlan_info->next_state,
           wlan_global->disc_flag, wlan_info->proc.ap->is_hidden, wlan_info->proc.ap->nw->ssid);

    wlan_set_max_reconnect_scan(1);

    wlan_info->proc.is_first = false;
    wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_GETTING_IP;
    wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_GETTING_IP;
    wlan_info->proc.ap->try_num++;
    wlan_info->proc.ap->pwd_err_num = 0;

    if(CM_GetConnectionSwitch()) {
        int32_t ret = CM_SetConnectionSwitch(false);
        printf("%s: stop lte, ret %d\n", __FUNCTION__, ret);
    }

    char * ifname = (char *)lwip_get_netif_uap_ifname();
    lwip_ifconfig_value(ifname, "ifstatus", LWIP_NETIF_IF_STATUS_DISABLE);
    lwip_ifconfig_value(ifname, "ifmode", LWIP_NETIF_IF_CLIENT_MODE);
    lwip_ifconfig_value(ifname, "proto4", LWIP_NETIF_IP_PROTOCOL_DHCP);

    hal_wlan_send_msg(HAL_WLAN_MSG_ID_NETIF_CONFIG, NULL);
}

static void hal_wlan_handle_act_ap_disc_event(void)
{
    printf("%s: ssid %s\n", __FUNCTION__, wlan_info->proc.ap->nw->ssid);

    hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_GET_IP);

    if(hal_wlan_get_cm_conn_setting()) {
        int32_t ret = CM_SetConnectionSwitch(true);
        printf("%s: switch to lte, ret %d\n", __FUNCTION__, ret);
    }

    if(HAL_WLAN_AP_STATE_GETTING_IP == wlan_info->proc.proc_state) {
        wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_OPEN_FAILED;
        wlan_info->proc.ap->conn_num++;
    } else {
        // priority to connect the last_act_ap, and then set the current ap as the last_act_ap
        wlan_info->last_disc_ap = wlan_info->proc.ap;
        wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_RETRY;
    }
    wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_SAVED;
    wlan_info->proc.ap = NULL;

    if(HAL_WLAN_STATE_SCAN != wlan_info->state) {
        hal_wlan_auto_open_ap();
    }
}

static void hal_wlan_reopen_ap(hal_wlan_saved_ap_t * ap)
{
    HAL_WLAN_SECURITY_T security;
    if(HAL_WLAN_SECURITY_UNSPECIFIED == ap->nw->security) {
        security = ap->alt_security;
    } else {
        security = ap->nw->security;
    }
    wlan_wifi_init_type_t init_info = {};
    init_info.wifi_mode = WLAN_STA;
    switch(security) {
    case HAL_WLAN_SECURITY_OPEN:
        init_info.security = WLAN_SECURITY_OPEN;
        break;
    case HAL_WLAN_SECURITY_WEP:
        init_info.security = WLAN_SECURITY_WEP;
        break;
    case HAL_WLAN_SECURITY_WPA:
        init_info.security = WLAN_SECURITY_WPA;
        break;
    case HAL_WLAN_SECURITY_WPA2:
        init_info.security = WLAN_SECURITY_WPA2;
        break;
    case HAL_WLAN_SECURITY_WPA_WPA2:
        init_info.security = WLAN_SECURITY_AUTO;
        break;
    default:
        break;
    }
    init_info.ssid_len = strlen(ap->nw->ssid);
    Hal_Mem_Copy(init_info.ssid, ap->nw->ssid, init_info.ssid_len);
    if(HAL_WLAN_SECURITY_OPEN != security) {
        init_info.key_len = strlen(ap->nw->pwd);
        if(0 < init_info.key_len) {
            Hal_Mem_Copy(init_info.key, ap->nw->pwd, init_info.key_len);
        }
    }
    int32_t ret = wlan_sta_connect(&init_info);
    printf("%s: wlan_sta_connect end, ret %d\n", __FUNCTION__, ret);
    if(0 > ret) {
        wlan_sta_err_status_e * err_status = Hal_Mem_Alloc(sizeof(wlan_sta_err_status_e));
        *err_status = WLAN_STA_MODE_NO_AP_FOUND;
        hal_wlan_send_msg(HAL_WLAN_MSG_ID_STA_DOWN, (void *)err_status);
    }
}

static void hal_wlan_handle_open_ap_fail_event(wlan_sta_err_status_e err_status)
{
    bool is_retry = false;
    if(wlan_info->last_act_ap
       && (HAL_WLAN_AP_STATE_RETRY == wlan_info->last_act_ap->state)) {
        // wait for new scanning result
        is_retry = true;
        wlan_info->last_act_ap->state = HAL_WLAN_AP_STATE_SAVED;
    }

    printf("%s: retry %d, first %d, ap state %d, ssid %s, try %d, conn %d, pwd err %d\n",
           __FUNCTION__, is_retry, wlan_info->proc.is_first, wlan_info->proc.ap->state,
           wlan_info->proc.ap->nw->ssid, wlan_info->proc.ap->try_num,
           wlan_info->proc.ap->conn_num, wlan_info->proc.ap->pwd_err_num);

    if(is_retry && (wlan_info->last_act_ap == wlan_info->proc.ap)) {
        printf("%s: retry failed\n", __FUNCTION__);
    } else {
        wlan_info->proc.ap->try_num++;
        if(WLAN_STA_MODE_PASSWORD_ERR == err_status) {
            wlan_info->proc.ap->pwd_err_num++;
        }
        if(HAL_WLAN_MAX_TRY_NUM > wlan_info->proc.ap->try_num) {
            hal_wlan_reopen_ap(wlan_info->proc.ap);
            return;
        } else {
            if(HAL_WLAN_MAX_TRY_NUM == wlan_info->proc.ap->pwd_err_num) {
                wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_PASSWORD_ERROR;
                wlan_info->proc.ap->conn_num = HAL_WLAN_MAX_CONN_NUM; // not allowed to be connected
                if(wlan_info->last_act_ap == wlan_info->proc.ap) {
                    wlan_info->last_act_ap = NULL;
                }
            } else {
                wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_OPEN_FAILED;
                wlan_info->proc.ap->conn_num++;
                if((HAL_WLAN_MAX_CONN_NUM == wlan_info->proc.ap->conn_num) &&
                   (wlan_info->last_act_ap == wlan_info->proc.ap)) {
                    wlan_info->last_act_ap = NULL;
                }
            }
        }
    }

    bool is_first = false;
    bool is_hidden = wlan_info->proc.ap->is_hidden;
    if(wlan_info->proc.is_first
       && (HAL_WLAN_AP_STATE_PASSWORD_ERROR == wlan_info->proc.ap->state)
       && !is_hidden) {
        is_first = true;
        hal_wlan_ins_ap_to_scan_list(wlan_info->proc.ap->nw->ssid, wlan_info->proc.ap->nw->security,
                                     wlan_info->proc.ap->power);
        hal_wlan_del_nw_from_nv(wlan_info->proc.ap->nw);
        _lv_ll_remove(&nw_list, wlan_info->proc.ap->nw);
        Hal_Mem_Free(wlan_info->proc.ap->nw);
        _lv_ll_remove(&wlan_info->saved_ap_list, wlan_info->proc.ap);
        Hal_Mem_Free(wlan_info->proc.ap);
    }
    wlan_info->proc.is_first = false;
    wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_SAVED;
    wlan_info->proc.ap = NULL;

    if((HAL_WLAN_STATE_SCAN == wlan_info->next_state)
        || is_retry) {
        wlan_info->state = HAL_WLAN_STATE_SCAN;
        wlan_info->next_state = HAL_WLAN_STATE_INIT;
        hal_wlan_start_scan();
    } else {
        hal_wlan_auto_open_ap();
    }

    if(is_first && !is_hidden) {
        hal_wlan_event_notification(HAL_WLAN_EVENT_OPEN_FAILED_WITH_PASSWORD_ERROR);
    }
}

static void hal_wlan_handle_open_ap_fail_event_without_security(wlan_sta_err_status_e err_status)
{
    bool is_retry = false;
    if(wlan_info->last_act_ap
       && (HAL_WLAN_AP_STATE_RETRY == wlan_info->last_act_ap->state)) {
        // wait for new scanning result
        is_retry = true;
        wlan_info->last_act_ap->state = HAL_WLAN_AP_STATE_SAVED;
    }

    printf("%s: retry %d, ap state %d, ssid %s\n", __FUNCTION__, is_retry,
           wlan_info->proc.ap->state, wlan_info->proc.ap->nw->ssid);

    if(is_retry && (wlan_info->last_act_ap == wlan_info->proc.ap)) {
        printf("%s: retry failed\n", __FUNCTION__);
    } else {
        wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_OPEN_FAILED;
    }
    wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_SAVED;
    wlan_info->proc.ap = NULL;

    if(HAL_WLAN_STATE_OPEN_NW_WITHOUT_SECURITY == wlan_info->state) {
        hal_wlan_auto_open_nw();
    } else if((HAL_WLAN_STATE_SCAN == wlan_info->next_state)
        || is_retry) {
        wlan_info->state = HAL_WLAN_STATE_SCAN;
        wlan_info->next_state = HAL_WLAN_STATE_INIT;
        hal_wlan_start_scan();
    } else {
        hal_wlan_auto_open_ap();
    }
}

static void hal_wlan_handle_wifi_reset(void)
{
    printf("%s\n", __FUNCTION__);

    wlan_global->reset_flag = true;

    char * ifname = (char *)lwip_get_netif_uap_ifname();
    if(ifname) {
        lwip_ifconfig_value(ifname, "ifstatus", LWIP_NETIF_IF_STATUS_DISABLE);
    }

    if(HAL_WLAN_STATE_SCAN == wlan_info->state) {
        wlan_info->state = HAL_WLAN_STATE_ON;
        hal_wlan_start_periodic_scan();
        hal_wlan_event_notification(HAL_WLAN_EVENT_STOP_SCAN_ABNORMAL);
    }

    wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_OPENING;
    wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_OPENING;
    wlan_info->state = HAL_WLAN_STATE_OPEN_AUTO;

    hal_wlan_open_ap(wlan_info->proc.ap);
}

static void hal_wlan_handle_wifi_reset_failed(void)
{
    printf("%s\n", __FUNCTION__);

    wlan_global->reset_flag = false;
    wlan_global->disc_flag = false;

    hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_GET_IP);

    if(hal_wlan_get_cm_conn_setting()) {
        int32_t ret = CM_SetConnectionSwitch(true);
        printf("%s: switch to lte, ret %d\n", __FUNCTION__, ret);
    }

    char * ifname = (char *)lwip_get_netif_uap_ifname();
    if(ifname) {
        lwip_ifconfig_value(ifname, "ifstatus", LWIP_NETIF_IF_STATUS_DISABLE);
    }

    wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_SAVED;
    wlan_info->proc.ap = NULL;

    if(HAL_WLAN_STATE_SCAN != wlan_info->next_state) {
        hal_wlan_auto_open_ap();
        hal_wlan_start_periodic_scan();
    } else {
        hal_wlan_start_scan();
    }
    hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
}

static void hal_wlan_hw_reset(void)
{
    wlan_hw_reset = HAL_WLAN_HW_RESET_PHASE_CLOSE;

    for(uint8_t i = 0;i < HAL_WLAN_MAX_TIMER_NUM;i++) {
        hal_wlan_timer_stop(i);
    }

    wlan_global->disc_flag = false;

    if(hal_wlan_get_cm_conn_setting()) {
        int32_t ret = CM_SetConnectionSwitch(true);
        printf("%s: switch to lte, ret %d\n", __FUNCTION__, ret);
    }

    if(wlan_info->proc.ap) {
        if(HAL_WLAN_AP_STATE_ACT == wlan_info->proc.ap->state) {
            wlan_info->last_act_ap = wlan_info->proc.ap;
        }
        wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_SAVED;
    }
    wlan_info->proc.ap = NULL;
    wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_SAVED;
    wlan_info->proc.is_first = false;

    if(HAL_WLAN_STATE_ON != wlan_info->state) {
        wlan_info->state = HAL_WLAN_STATE_ON;
        wlan_info->next_state = HAL_WLAN_STATE_INIT;
    }

    hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);

    wlan_set_close_cause(1);
    printf("%s: wlan_wifi_close start\n", __FUNCTION__);
    int32_t ret = wlan_wifi_close();
    printf("%s: wlan_wifi_close, ret %d\n", __FUNCTION__, ret);

    sdio_wifi_close();

    wlan_global->max_periodic_timeout_count = 1;
    hal_wlan_timer_start(HAL_WLAN_TIMER_ID_PERIOD_SCAN);
}

static void hal_wlan_adp_sta_down_msg(void * data)
{
    if(NULL == data) {
        printf("%s: warning, data is NULL\n", __FUNCTION__);
        return;
    }

    wlan_sta_err_status_e err_status = *((wlan_sta_err_status_e *)data);

    printf("%s: state %d:%d, disc %d, reset %d, err_status %d, proc_state %d, hw reset %d\n",
           __FUNCTION__, wlan_info->state, wlan_info->next_state, wlan_global->disc_flag,
           wlan_global->reset_flag, err_status, wlan_info->proc.proc_state, wlan_hw_reset);

    if(HAL_WLAN_HW_RESET_PHASE_NULL != wlan_hw_reset) {
        return;
    }

    if(WLAN_FW_NEED_HW_RESET == err_status) {
        hal_wlan_hw_reset();
#if USE_LV_BLUETOOTH != 0
        if(wlan_bt_firmware_assert()) {
            return;
        }
#endif
        hal_wlan_hw_reset_end();
        return;
    } else if(WLAN_STA_MODE_CONN_RESET == err_status) {
        printf("%s: wifi reset\n", __FUNCTION__);
        if(wlan_global->disc_flag) {
            err_status = WLAN_STA_MODE_USER_CLOSE;
        } else if((HAL_WLAN_AP_STATE_OPENING == wlan_info->proc.proc_state)
                  || (HAL_WLAN_AP_STATE_GETTING_IP == wlan_info->proc.proc_state)) {
            if(hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_GET_IP)) {
                char * ifname = (char *)lwip_get_netif_uap_ifname();
                if(ifname) {
                    lwip_ifconfig_value(ifname, "ifstatus", LWIP_NETIF_IF_STATUS_DISABLE);
                }
            }
            wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_OPENING;
            wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_OPENING;
            hal_wlan_open_ap(wlan_info->proc.ap);
            return;
        } else if(HAL_WLAN_AP_STATE_ACT == wlan_info->proc.proc_state) {
            hal_wlan_handle_wifi_reset();
            return;
        } else if(HAL_WLAN_STATE_SCAN == wlan_info->state) {
            hal_wlan_start_scan();
            return;
        }
    } else if(wlan_global->reset_flag) {
        hal_wlan_handle_wifi_reset_failed();
        return;
    }

    if(wlan_global->disc_flag) {
        if((WLAN_STA_MODE_USER_CLOSE != err_status) &&
           (WLAN_STA_MODE_CONN_RETRY_MAX != err_status)) {
            printf("%s: warning, conflict between disconnect and connect fail\n", __FUNCTION__);
            return;
        }

        wlan_global->disc_flag = false;

        if(HAL_WLAN_AP_STATE_GETTING_IP == wlan_info->proc.proc_state) {
            wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_SAVED;
            if(wlan_info->proc.ap) {
                wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_OPEN_FAILED;
                wlan_info->proc.ap->conn_num++;
                wlan_info->proc.ap = NULL;
            }
            if(HAL_WLAN_STATE_OPEN_NW_WITHOUT_SECURITY == wlan_info->state) {
                hal_wlan_auto_open_nw();
            } else if(HAL_WLAN_STATE_SCAN == wlan_info->next_state) {
                wlan_info->state = HAL_WLAN_STATE_SCAN;
                wlan_info->next_state = HAL_WLAN_STATE_INIT;
                hal_wlan_start_scan();
            } else {
                hal_wlan_auto_open_ap();
            }

            hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
            return;
        }

        if(HAL_WLAN_STATE_SCAN == wlan_info->state) {
            printf("%s: waiting for scanning result\n", __FUNCTION__);
        } else if((HAL_WLAN_STATE_OPEN_SPEC == wlan_info->state)
            || (HAL_WLAN_STATE_OPEN_AUTO == wlan_info->state)) {
            hal_wlan_open_ap(wlan_info->proc.ap);
        } else if(HAL_WLAN_STATE_OPEN_NW_WITHOUT_SECURITY == wlan_info->state) {
            hal_wlan_auto_open_nw();
        } else {
            hal_wlan_auto_open_ap();
            if(HAL_WLAN_STATE_ON != wlan_info->state) {
                hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
            }
        }

        return;
    }

    if(wlan_global->reset_flag
       && (WLAN_STA_MODE_CONN_RESET != err_status)) {
    } else if(wlan_info->proc.ap
       && ((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.proc_state)
           || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.proc_state)
           || (HAL_WLAN_AP_STATE_GETTING_IP == wlan_info->proc.proc_state))) {
        hal_wlan_handle_act_ap_disc_event();
    } else if(wlan_info->proc.ap
              && (HAL_WLAN_AP_STATE_OPENING == wlan_info->proc.proc_state)) {
        if(WLAN_STA_MODE_CONN_RETRY_MAX == err_status) {
            printf("%s: error, rcv wrong err status %d during opening process\n", __FUNCTION__, err_status);
            return;
        }
        if(HAL_WLAN_SECURITY_UNSPECIFIED == wlan_info->proc.ap->nw->security) {
            hal_wlan_handle_open_ap_fail_event_without_security(err_status);
        } else {
            hal_wlan_handle_open_ap_fail_event(err_status);
        }
    } else {
        printf("%s: no act ap and open ap\n", __FUNCTION__);
    }

    hal_wlan_start_periodic_scan();
    hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
}

static void hal_wlan_adp_act_ap_rssi_msg(void * data)
{
    if(NULL == data) {
        printf("%s: warning, data is NULL\n", __FUNCTION__);
        return;
    }

    int8_t rssi_signal = *((int8_t *)data);

    if(NULL == wlan_info->proc.ap) {
        printf("%s: warning, no proc ap\n", __FUNCTION__);
        return;
    }

    if((HAL_WLAN_AP_STATE_ACT != wlan_info->proc.proc_state)
       && (HAL_WLAN_AP_STATE_NO_INTERNET != wlan_info->proc.proc_state)
       && (HAL_WLAN_AP_STATE_GETTING_IP != wlan_info->proc.proc_state)) {
        printf("%s: warning, not act ap\n", __FUNCTION__);
        return;
    }

    if(rssi_signal == wlan_info->proc.ap->power) {
        printf("%s: rssi is not changed\n", __FUNCTION__);
        return;
    }

    uint8_t old_level = hal_wlan_rssi_level_calc(wlan_info->proc.ap->power);
    uint8_t new_level = hal_wlan_rssi_level_calc(rssi_signal);

    wlan_info->proc.ap->power = rssi_signal;
    hal_wlan_sort_saved_ap_by_power(wlan_info->proc.ap);

    printf("%s: rssi level old %d, new %d, state %d:%d, ssid %s\n", __FUNCTION__, old_level,
           new_level, wlan_info->state, wlan_info->next_state, wlan_info->proc.ap->nw->ssid);

    if(old_level != new_level) {
        if(HAL_WLAN_STATE_ON == wlan_info->state) {
            hal_wlan_auto_open_ap();
        }
        if((HAL_WLAN_STATE_ON == wlan_info->state)
            || (HAL_WLAN_STATE_SCAN == wlan_info->state)) {
            hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_ACT_AP_RSSI);
        } else {
            hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
        }
    }
}

static void hal_wlan_adp_lcd_wakeup_msg(void)
{
    printf("%s: stat %d:%d, is_in_ui %d, noti_ind %d\n", __FUNCTION__, wlan_info->state,
           wlan_info->next_state, is_in_wlan_ui, wlan_global->event_noti_ind);

    if(false == is_in_wlan_ui) {
        wlan_global->event_noti_ind = false;
        return;
    }

    wlan_global->max_periodic_timeout_count = HAL_WLAN_RESCAN_INTERVAL;

    if((HAL_WLAN_STATE_SCAN == wlan_info->state)
        || (HAL_WLAN_STATE_SCAN == wlan_info->next_state)) {
        if(wlan_global->event_noti_ind) {
            wlan_global->event_noti_ind = false;
            hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
        }
        return;
    }

    if(wlan_timer[HAL_WLAN_TIMER_ID_PERIOD_SCAN].is_running) {
        if(HAL_WLAN_RESCAN_INTERVAL > wlan_timer[HAL_WLAN_TIMER_ID_PERIOD_SCAN].timeout_count) {
            if(wlan_global->event_noti_ind) {
                wlan_global->event_noti_ind = false;
                hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
            }
            return;
        }

        hal_wlan_timer_stop(HAL_WLAN_TIMER_ID_PERIOD_SCAN);
    }

    if(HAL_WLAN_STATE_ON != wlan_info->state) {
        wlan_info->next_state = HAL_WLAN_STATE_SCAN;
    } else {
        wlan_info->state = HAL_WLAN_STATE_SCAN;
        if(false == wlan_global->disc_flag) {
            hal_wlan_start_scan();
        }
    }
    if(wlan_global->event_noti_ind) {
        wlan_global->event_noti_ind = false;
        hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
    } else {
        hal_wlan_event_notification(HAL_WLAN_EVENT_START_SCAN);
    }
}

static void hal_wlan_adp_netif_config_msg(void)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return;
    }

    if(!wlan_info->proc.ap) {
        return;
    }

    if(HAL_WLAN_AP_STATE_GETTING_IP != wlan_info->proc.proc_state) {
        return;
    }

    char * ifname = (char *)lwip_get_netif_uap_ifname();
    lwip_ifconfig_value(ifname, "ifact4", LWIP_NETIF_IF_STATUS_ACTIVE);

    wlan_sta_signal_level_t signal_level;
    if(0 == wlan_sta_signal_level_get(&signal_level)) {
        int8_t * data = Hal_Mem_Alloc(sizeof(int8_t));
        *data = signal_level.rssi_signal;
        hal_wlan_send_msg(HAL_WLAN_MSG_ID_ACT_AP_RSSI, (void *)data);
    } else {
        printf("%s: get rssi failed\n", __FUNCTION__);
    }

    Hal_Mem_Set(wlan_info->ip, 0, 16);
#ifdef BUILD_IN_PC_SIMULATOR
    lv_task_t * task = lv_task_create(hal_wlan_getting_ip_task_cb, 4000, LV_TASK_PRIO_HIGH, NULL);
    lv_task_once(task);
#else
    hal_wlan_timer_start(HAL_WLAN_TIMER_ID_GET_IP);
#endif
    printf("%s: getting ip\n", __FUNCTION__);
    hal_wlan_event_notification(HAL_WLAN_EVENT_GETTING_IP);
}

static void hal_wlan_adp_get_ip_msg(void)
{
    if(NULL == wlan_info->proc.ap) {
        printf("%s: proc ap is NULL\n", __FUNCTION__);
        return;
    }

    if(HAL_WLAN_AP_STATE_GETTING_IP != wlan_info->proc.proc_state) {
        printf("%s: not get ip\n", __FUNCTION__);
        return;
    }

    printf("%s: ip %s\n", __FUNCTION__, wlan_info->ip);

    wifi_inform_dhcp_complete();

    if(wlan_info->last_act_ap == wlan_info->proc.ap) {
        wlan_info->last_act_ap = NULL;
    } else if(wlan_info->last_act_ap
              && (HAL_WLAN_AP_STATE_RETRY == wlan_info->last_act_ap->state)) {
        wlan_info->last_act_ap->state = HAL_WLAN_AP_STATE_SAVED;
    }

    wlan_info->proc.ap->state = HAL_WLAN_AP_STATE_ACT;
    wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_ACT;
    wlan_info->proc.ap->try_num = 0;
    wlan_info->proc.ap->conn_num = 0;
    wlan_info->proc.ap->pwd_err_num = 0;

    if(HAL_WLAN_STATE_SCAN == wlan_info->next_state) {
        wlan_info->state = HAL_WLAN_STATE_SCAN;
        hal_wlan_start_scan();
    } else {
        wlan_info->state = HAL_WLAN_STATE_ON;
    }
    wlan_info->next_state = HAL_WLAN_STATE_INIT;
    wlan_info->opening_nw = NULL;
    hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);

    if(wlan_global->reset_flag) {
        wlan_global->reset_flag = false;
    }

    get_ntp_time();
}

static void hal_wlan_adp_proc_continue_msg(void)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return;
    }

    printf("%s: wait_bt_open_flag %d, state %d\n",
           __FUNCTION__, wlan_global->wait_bt_open_flag, wlan_info->state);

    if(!wlan_global->wait_bt_open_flag) {
        return;
    }

    if(wlan_info->state != HAL_WLAN_STATE_SCAN) {
        return;
    }

    wlan_global->wait_bt_open_flag = false;

    hal_wlan_start_scan();
}

static void hal_wlan_adp_hw_reset_start_msg(void)
{
    if(HAL_WLAN_HW_RESET_PHASE_NULL != wlan_hw_reset) {
        printf("%s: warning, performing hw reset\n", __FUNCTION__);
        return;
    }

    printf("%s: state %d:%d\n", __FUNCTION__, wlan_info->state, wlan_info->next_state);

    if(hal_wlan_is_opened(__FUNCTION__)) {
        hal_wlan_hw_reset();
    }

#if USE_LV_BLUETOOTH != 0
    if(wlan_bt_firmware_assert()) {
        return;
    }
#endif

    hal_wlan_hw_reset_end();
}

static void hal_wlan_hw_reset_open_process(void)
{
    wlan_wifi_init_type_t init_info = {};
    init_info.wifi_mode = WLAN_STA;
    int32_t ret = wlan_wifi_open(&init_info);
    printf("%s: wlan_wifi_open, ret %d\n", __FUNCTION__, ret);

    if(0 != ret) {
        hal_wlan_send_msg(HAL_WLAN_MSG_ID_SDIO_OPEN_FAILED, NULL);
        return;
    }

    wlan_scan_compeleted_cb_register(hal_wlan_scan_cb);
    wlan_stat_chg_cb_register(hal_wlan_ap_state_chg_cb);
    wlan_sta_rssi_cb_register(hal_wlan_act_ap_rssi_level_cb);

#if USE_LV_BLUETOOTH != 0
    wlan_bt_recover_connection_fw_assert();
#endif

    wlan_hw_reset = HAL_WLAN_HW_RESET_PHASE_NULL;

    if(HAL_WLAN_STATE_SCAN == wlan_info->state) {
        hal_wlan_start_scan();
    } else if(HAL_WLAN_STATE_OPEN_SPEC == wlan_info->state) {
        if(wlan_info->proc.ap) {
            hal_wlan_open_ap(wlan_info->proc.ap);
        } else {
            printf("%s: warning, not ap which is waiting for opening\n", __FUNCTION__);
            if(HAL_WLAN_STATE_SCAN == wlan_info->next_state) {
                wlan_info->state = HAL_WLAN_STATE_SCAN;
                wlan_info->next_state = HAL_WLAN_STATE_INIT;
                hal_wlan_start_scan();
                hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
            }
        }
    }
}

static void hal_wlan_adp_hw_reset_end_msg(void)
{
    printf("%s: hw reset %d, state %d:%d\n",
           __FUNCTION__, wlan_hw_reset, wlan_info->state, wlan_info->next_state);

    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return;
    }

    if(HAL_WLAN_HW_RESET_PHASE_CLOSE != wlan_hw_reset) {
        return;
    }

    int32_t ret = sdio_wifi_open();
    printf("%s: sdio_wifi_open, ret %d\n", __FUNCTION__, ret);

    wlan_hw_reset = HAL_WLAN_HW_RESET_PHASE_OPEN;

    if(0 != ret) {
        hal_wlan_send_msg(HAL_WLAN_MSG_ID_SDIO_OPEN_FAILED, NULL);
        return;
    }

#ifndef BUILD_IN_PC_SIMULATOR
    if(1 != GetWifiConfigFlag()) {
        hal_wlan_timer_start(HAL_WLAN_TIMER_ID_CHECK_SDIO_CFG);
        return;
    }
#endif

    hal_wlan_hw_reset_open_process();
}

static void hal_wlan_adp_sdio_open_success_msg(void)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return;
    }

    if(HAL_WLAN_HW_RESET_PHASE_NULL == wlan_hw_reset) {
        wlan_wifi_init_type_t init_info = {};
        init_info.wifi_mode = WLAN_STA;
        if(0 == wlan_wifi_open(&init_info)) {
            printf("%s: wlan_wifi_open ok\n", __FUNCTION__);
            hal_wlan_open_process();
        } else {
            printf("%s: wlan_wifi_open ng\n", __FUNCTION__);
            hal_wlan_close_wlan(false);
            hal_wlan_open_bt();
        }
    } else if(HAL_WLAN_HW_RESET_PHASE_OPEN == wlan_hw_reset) {
        hal_wlan_hw_reset_open_process();
    }
}

static void hal_wlan_adp_sdio_open_failed_msg(void)
{
    if(false == hal_wlan_is_opened(__FUNCTION__)) {
        return;
    }

    if(HAL_WLAN_HW_RESET_PHASE_NULL == wlan_hw_reset) {
        hal_wlan_close_wlan(false);
        hal_wlan_open_bt();
    } else if(HAL_WLAN_HW_RESET_PHASE_OPEN == wlan_hw_reset) {
        hal_wlan_close_wlan(true);
#if USE_LV_BLUETOOTH != 0
        wlan_bt_recover_connection_fw_assert();
#endif
    }
}

static void hal_wlan_adp_open_wlan_without_security_msg(void)
{
    int32_t ret = sdio_wifi_open();
    printf("%s: sdio_wifi_open, ret %d\n", __FUNCTION__, ret);

    if(0 == ret) {
        wlan_wifi_init_type_t init_info = {};
        init_info.wifi_mode = WLAN_STA;
        ret = wlan_wifi_open(&init_info);
        printf("%s: wlan_wifi_open, ret %d\n", __FUNCTION__, ret);

        if(0 == ret) {
            char * ifname = (char *)lwip_get_netif_uap_ifname();
            if(ifname) {
                wlan_scan_compeleted_cb_register(hal_wlan_scan_cb);
                wlan_stat_chg_cb_register(hal_wlan_ap_state_chg_cb);
                wlan_sta_rssi_cb_register(hal_wlan_act_ap_rssi_level_cb);

                wlan_info->opening_nw = hal_wlan_handle_buffered_msg(wlan_info->opening_nw);
                hal_wlan_nw_t * nw = _lv_ll_get_head(&nw_list);
#ifndef BUILD_IN_PC_SIMULATOR
                if(NULL == nw) {
                    printf("%s: no nw and close wlan\n", __FUNCTION__);
                    hal_wlan_close_wlan_without_security();
                    return;
                }
#endif

                while(nw) {
                    if('\0' == nw->pwd[0]) {
                        hal_wlan_saved_ap_t * ap = _lv_ll_ins_tail(&wlan_info->saved_ap_list);
                        Hal_Mem_Set(ap, 0, sizeof(hal_wlan_saved_ap_t));
                        ap->nw = nw;
                        ap->alt_security = HAL_WLAN_SECURITY_OPEN;
                    } else {
                        for(uint8_t i = HAL_WLAN_SECURITY_WEP;
                            i < HAL_WLAN_SECURITY_UNSPECIFIED;i++) {
                            hal_wlan_saved_ap_t * ap = _lv_ll_ins_tail(&wlan_info->saved_ap_list);
                            Hal_Mem_Set(ap, 0, sizeof(hal_wlan_saved_ap_t));
                            ap->nw = nw;
                            ap->alt_security = i;
                        }
                    }
                    nw = _lv_ll_get_next(&nw_list, nw);
                }

                wlan_info->state = HAL_WLAN_STATE_SCAN;
                hal_wlan_start_scan();

                if(wlan_info->opening_nw) {
                    printf("%s: open nw %s\n", __FUNCTION__, wlan_info->opening_nw->ssid);
                    wlan_info->next_state = HAL_WLAN_STATE_OPEN_NW_WITHOUT_SECURITY;
                }

                hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);

                return;
            }
        }
    }

    hal_wlan_close_wlan_without_security();
}

static void hal_wlan_adp_open_nw_without_security_msg(void * data)
{
    if(NULL == data) {
        printf("%s: warning, data is NULL\n", __FUNCTION__);
        return;
    }

    printf("%s: state %d, next state %d\n",
           __FUNCTION__, wlan_info->state, wlan_info->next_state);

    hal_wlan_nw_t * spec_nw = (hal_wlan_nw_t *)data;
    hal_wlan_nw_t * nw = _lv_ll_get_head(&nw_list);
    while(nw) {
        if(0 == strcmp(nw->ssid, spec_nw->ssid)) {
            break;
        }
        nw = _lv_ll_get_next(&nw_list, nw);
    }
    uint8_t new_pwd_len = strlen(spec_nw->pwd);
    bool is_new_nw = false;
    bool is_pwd_changed = false;
    bool is_security_changed = false;
    if(nw) {
        printf("%s: old pwd %s\n", __FUNCTION__, nw->pwd);
        if(0 != strcmp(nw->pwd, spec_nw->pwd)) {
            is_pwd_changed = true;
            uint8_t old_pwd_len = strlen(nw->pwd);
            Hal_Mem_Copy(nw->pwd, spec_nw->pwd, HAL_WLAN_MAX_PWD_LEN + 1);
            hal_wlan_chg_pwd_to_nv(nw);

            if(((0 == new_pwd_len) && (0 < old_pwd_len))
               || ((0 < new_pwd_len) && (0 == old_pwd_len))) {
                is_security_changed = true;
                uint8_t count = 1;
                if(0 < new_pwd_len) {
                    count = HAL_WLAN_SECURITY_MAX - 1;
                }
                hal_wlan_saved_ap_t * saved_ap = _lv_ll_get_head(&wlan_info->saved_ap_list);
                while(saved_ap) {
                    hal_wlan_saved_ap_t * temp = _lv_ll_get_next(&wlan_info->saved_ap_list, saved_ap);
                    if(nw == saved_ap->nw) {
                        if((false == saved_ap->is_hidden) && (0 != saved_ap->power)) {
                            hal_wlan_ins_ap_to_scan_list(saved_ap->nw->ssid, saved_ap->alt_security,
                                                         saved_ap->power);
                        }
                        _lv_ll_remove(&wlan_info->saved_ap_list, saved_ap);
                        Hal_Mem_Free(saved_ap);
                        count--;
                        if(0 == count) {
                            break;
                        }
                    }
                    saved_ap = temp;
                }
            }
        }
    } else {
        is_new_nw = true;
        printf("%s: add new nw\n", __FUNCTION__);
        nw = _lv_ll_ins_tail(&nw_list);
        Hal_Mem_Copy(nw, spec_nw, sizeof(hal_wlan_nw_t));
        hal_wlan_add_new_nw_to_nv(nw);
    }

    if(is_new_nw || is_security_changed) {
        hal_wlan_saved_ap_t * new_saved_ap[HAL_WLAN_SECURITY_MAX] = {};
        if(0 == new_pwd_len) {
            new_saved_ap[0] = _lv_ll_ins_head(&wlan_info->saved_ap_list);
            Hal_Mem_Set(new_saved_ap[0], 0, sizeof(hal_wlan_saved_ap_t));
            new_saved_ap[0]->nw = nw;
            new_saved_ap[0]->alt_security = HAL_WLAN_SECURITY_OPEN;
        } else {
            for(uint8_t i = HAL_WLAN_SECURITY_WEP;i < HAL_WLAN_SECURITY_MAX;i++) {
                new_saved_ap[i] = _lv_ll_ins_head(&wlan_info->saved_ap_list);
                Hal_Mem_Set(new_saved_ap[i], 0, sizeof(hal_wlan_saved_ap_t));
                new_saved_ap[i]->nw = nw;
                new_saved_ap[i]->alt_security = i;
            }
        }

        hal_wlan_ap_t * ap = _lv_ll_get_head(&wlan_info->scan_list);
        while(ap) {
            if(0 == strcmp(nw->ssid, ap->ssid)) {
                if(((0 == new_pwd_len)
                    && (HAL_WLAN_SECURITY_OPEN == ap->security))
                   || ((0 != new_pwd_len)
                       && (HAL_WLAN_SECURITY_OPEN != ap->security))) {
                    new_saved_ap[ap->security]->power = ap->power;
                    hal_wlan_sort_saved_ap_by_power(new_saved_ap[ap->security]);

                    if(HAL_WLAN_SECURITY_OPEN == ap->security) {
                        break;
                    }
                }
            }
            ap = _lv_ll_get_next(&wlan_info->scan_list, ap);
        }
        if(0 == new_pwd_len) {
            if((0 == new_saved_ap[HAL_WLAN_SECURITY_OPEN]->power)
               && (0 != wlan_info->hid_ap_power[HAL_WLAN_SECURITY_OPEN])) {
                new_saved_ap[HAL_WLAN_SECURITY_OPEN]->power
                    = wlan_info->hid_ap_power[HAL_WLAN_SECURITY_OPEN];
                new_saved_ap[HAL_WLAN_SECURITY_OPEN]->is_hidden = true;
                hal_wlan_sort_saved_ap_by_power(new_saved_ap[HAL_WLAN_SECURITY_OPEN]);
            }
        } else {
            for(uint8_t i = HAL_WLAN_SECURITY_WEP;i < HAL_WLAN_SECURITY_MAX;i++) {
                if((0 == new_saved_ap[i]->power)
                   && (0 != wlan_info->hid_ap_power[i])) {
                    new_saved_ap[i]->power = wlan_info->hid_ap_power[i];
                    new_saved_ap[i]->is_hidden = true;
                    hal_wlan_sort_saved_ap_by_power(new_saved_ap[i]);
                }
            }
        }
    }

    if(wlan_info->proc.ap) {
        if(nw == wlan_info->proc.ap->nw) {
            if(false == is_pwd_changed) {
                if((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.proc_state)
                   || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.proc_state)) {
                    printf("%s: open an act nw\n", __FUNCTION__);
                } else {
                    printf("%s: open a opening nw\n", __FUNCTION__);
                    if(HAL_WLAN_STATE_OPEN_AUTO == wlan_info->state) {
                        wlan_info->state = HAL_WLAN_STATE_OPEN_NW_WITHOUT_SECURITY;
                        wlan_info->opening_nw = nw;
                    }
                }
                return;
            } else {
                if((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.proc_state)
                   || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.proc_state)
                   || (HAL_WLAN_AP_STATE_GETTING_IP == wlan_info->proc.proc_state)) {
                    printf("%s: open an act nw with pwd changed, state %d\n",
                           __FUNCTION__, wlan_info->proc.proc_state);
                    hal_wlan_prepare_to_disconnect();
                } else {
                    printf("%s: open a opening nw with pwd changed\n", __FUNCTION__);
                    hal_wlan_disc_opening_process();
                }
            }
        } else {
            if((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.proc_state)
               || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.proc_state)
               || (HAL_WLAN_AP_STATE_GETTING_IP == wlan_info->proc.proc_state)) {
                printf("%s: disc act ap, state %d\n", __FUNCTION__, wlan_info->proc.proc_state);
                if((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.proc_state)
                   || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.proc_state)) {
                    wlan_info->last_act_ap = wlan_info->proc.ap;
                    wlan_info->last_act_ap->state = HAL_WLAN_AP_STATE_SAVED;
                }
                hal_wlan_prepare_to_disconnect();
            } else {
                printf("%s: interrupt opening nw\n", __FUNCTION__);
                hal_wlan_disc_opening_process();
            }
        }
    }

    wlan_info->opening_nw = nw;
    wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_SAVED;
    wlan_info->proc.ap = NULL;

    if(HAL_WLAN_STATE_SCAN == wlan_info->state) {
        wlan_info->next_state = HAL_WLAN_STATE_OPEN_NW_WITHOUT_SECURITY;
    } else if(HAL_WLAN_STATE_SCAN == wlan_info->next_state) {
        wlan_info->state = HAL_WLAN_STATE_SCAN;
        wlan_info->next_state = HAL_WLAN_STATE_OPEN_NW_WITHOUT_SECURITY;
        hal_wlan_start_scan();
    } else {
        wlan_info->state = HAL_WLAN_STATE_OPEN_NW_WITHOUT_SECURITY;
        if(false == wlan_global->disc_flag) {
            hal_wlan_auto_open_nw();
        }
    }
    hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
}

static void hal_wlan_adp_del_nw_without_security_msg(void * data)
{
    if(NULL == data) {
        printf("%s: data is NULL\n", __FUNCTION__);
        return;
    }

    hal_wlan_nw_t * del_nw = (hal_wlan_nw_t *)data;

    printf("%s: state %d:%d, flag %d, ssid %s\n", __FUNCTION__, wlan_info->state,
           wlan_info->next_state, wlan_global->disc_flag, del_nw->ssid);

    hal_wlan_nw_t * nw = _lv_ll_get_head(&nw_list);
    while(nw) {
        printf("%s: nw->ssid %s\n", __FUNCTION__, nw->ssid);
        if(0 == strcmp(nw->ssid, del_nw->ssid)) {
            break;
        }
        nw = _lv_ll_get_next(&nw_list, nw);
    }
    if(NULL == nw) {
        printf("%s: warning, not find nw\n", __FUNCTION__);
        return;
    }

    _lv_ll_remove(&nw_list, nw);
    hal_wlan_del_nw_from_nv(nw);

    if(wlan_info->last_disc_ap && (nw == wlan_info->last_disc_ap->nw)) {
        wlan_info->last_disc_ap = NULL;
    }
    if(wlan_info->last_act_ap && (nw == wlan_info->last_act_ap->nw)) {
        wlan_info->last_act_ap = NULL;
    }

    if(NULL == _lv_ll_get_head(&nw_list)) {
        Hal_Mem_Free(nw);
        hal_wlan_close_wlan_without_security();
        return;
    }

    if(wlan_info->proc.ap && (nw == wlan_info->proc.ap->nw)) {
        if((HAL_WLAN_AP_STATE_ACT == wlan_info->proc.proc_state)
           || (HAL_WLAN_AP_STATE_NO_INTERNET == wlan_info->proc.proc_state)
           || (HAL_WLAN_AP_STATE_GETTING_IP == wlan_info->proc.proc_state)) {
            printf("%s: del an act nw, state %d\n", __FUNCTION__, wlan_info->proc.proc_state);
            hal_wlan_prepare_to_disconnect();
        } else {
            printf("%s: del a opening nw\n", __FUNCTION__);
            hal_wlan_disc_opening_process();
        }

        wlan_info->proc.ap = NULL;
        if(HAL_WLAN_AP_STATE_GETTING_IP != wlan_info->proc.proc_state) {
            wlan_info->proc.proc_state = HAL_WLAN_AP_STATE_SAVED;
        }
    }

    uint8_t count = 1;
    if(0 < strlen(nw->pwd)) {
        count = HAL_WLAN_SECURITY_MAX - 1;
    }
    hal_wlan_saved_ap_t * saved_ap = _lv_ll_get_head(&wlan_info->saved_ap_list);
    while(saved_ap) {
        hal_wlan_saved_ap_t * temp = _lv_ll_get_next(&wlan_info->saved_ap_list, saved_ap);
        if(nw == saved_ap->nw) {
            if(0 != saved_ap->power) {
                hal_wlan_ins_ap_to_scan_list(saved_ap->nw->ssid, saved_ap->alt_security,
                                             saved_ap->power);
            }
            _lv_ll_remove(&wlan_info->saved_ap_list, saved_ap);
            Hal_Mem_Free(saved_ap);
            count--;
            if(0 == count) {
                break;
            }
        }
        saved_ap = temp;
    }

    if(nw == wlan_info->opening_nw) {
        wlan_info->opening_nw = NULL;
        if(HAL_WLAN_STATE_OPEN_NW_WITHOUT_SECURITY == wlan_info->state) {
            if(HAL_WLAN_STATE_SCAN == wlan_info->next_state) {
                wlan_info->state = HAL_WLAN_STATE_SCAN;
                wlan_info->next_state = HAL_WLAN_STATE_INIT;
                hal_wlan_start_scan();
            } else {
                hal_wlan_auto_open_ap();
            }
        } else if(HAL_WLAN_STATE_OPEN_NW_WITHOUT_SECURITY == wlan_info->next_state) {
            wlan_info->next_state = HAL_WLAN_STATE_INIT;
        } else {
            printf("%s: warning, wrong state\n", __FUNCTION__);
        }
    }

    Hal_Mem_Free(nw);

    hal_wlan_event_notification(HAL_WLAN_EVENT_UPDATE_AP_LIST);
}

static void hal_wlan_adp_main(void * para)
{
    hal_wlan_msg_t * msg;

    while(!adp_task_id) {
        uos_sleep(10);
    }

    // get msg
    while(1) {
        // receive message
        msg = (hal_wlan_msg_t *)Hal_Receive_Message((TASK_ID)adp_task_id, true);

        printf("%s: rcv msg id %d\n", __FUNCTION__, msg->id);
        switch(msg->id) {
        case HAL_WLAN_MSG_ID_OPEN_WLAN:
            hal_wlan_adp_open_wlan_msg();
            break;
        case HAL_WLAN_MSG_ID_CLOSE_WLAN:
            hal_wlan_adp_close_wlan_msg();
            break;
        case HAL_WLAN_MSG_ID_RESET:
            hal_wlan_adp_reset_msg();
            break;
        case HAL_WLAN_MSG_ID_SCAN_AP:
            hal_wlan_adp_scan_ap_msg();
            break;
        case HAL_WLAN_MSG_ID_SCAN_RESULT:
            hal_wlan_adp_scan_result_msg(msg->msg);
            break;
        case HAL_WLAN_MSG_ID_PERIODIC_SCAN:
            hal_wlan_adp_periodic_scan_msg();
            break;
        case HAL_WLAN_MSG_ID_OPEN_AP:
            hal_wlan_adp_open_ap_msg(msg->msg);
            break;
        case HAL_WLAN_MSG_ID_UI_STATE_CHG:
            hal_wlan_adp_ui_state_chg_msg(msg->msg);
            break;
        case HAL_WLAN_MSG_ID_DEL_NW:
            hal_wlan_adp_del_nw_msg(msg->msg);
            break;
        case HAL_WLAN_MSG_ID_SET_AUTO_SEL_NW:
            hal_wlan_adp_set_auto_sel_nw_msg(msg->msg);
            break;
        case HAL_WLAN_MSG_ID_DISCONNECT:
            hal_wlan_adp_disconnect_msg(msg->msg);
            break;
        case HAL_WLAN_MSG_ID_STA_UP:
            hal_wlan_adp_sta_up_msg();
            break;
        case HAL_WLAN_MSG_ID_STA_DOWN:
            hal_wlan_adp_sta_down_msg(msg->msg);
            break;
        case HAL_WLAN_MSG_ID_ACT_AP_RSSI:
            hal_wlan_adp_act_ap_rssi_msg(msg->msg);
            break;
        case HAL_WLAN_MSG_ID_LCD_WAKEUP:
            hal_wlan_adp_lcd_wakeup_msg();
            break;
        case HAL_WLAN_MSG_ID_NETIF_CONFIG:
            hal_wlan_adp_netif_config_msg();
            break;
        case HAL_WLAN_MSG_ID_GET_IP:
            hal_wlan_adp_get_ip_msg();
            break;
        case HAL_WLAN_MSG_ID_PROC_CONTINUE:
            hal_wlan_adp_proc_continue_msg();
            break;
        case HAL_WLAN_MSG_ID_HW_RESET_START:
            hal_wlan_adp_hw_reset_start_msg();
            break;
        case HAL_WLAN_MSG_ID_HW_RESET_END:
            hal_wlan_adp_hw_reset_end_msg();
            break;
        case HAL_WLAN_MSG_ID_OPEN_WLAN_WITHOUT_SECURITY:
            hal_wlan_adp_open_wlan_without_security_msg();
            break;
        case HAL_WLAN_MSG_ID_OPEN_NW_WITHOUT_SECURITY:
            hal_wlan_adp_open_nw_without_security_msg(msg->msg);
            break;
        case HAL_WLAN_MSG_ID_DEL_NW_WITHOUT_SECURITY:
            hal_wlan_adp_del_nw_without_security_msg(msg->msg);
            break;
        case HAL_WLAN_MSG_ID_SDIO_OPEN_SUCCESS:
            hal_wlan_adp_sdio_open_success_msg();
            break;
        case HAL_WLAN_MSG_ID_SDIO_OPEN_FAILED:
            hal_wlan_adp_sdio_open_failed_msg();
            break;
        default:
            printf("%s: wrong msg\n", __FUNCTION__);
            break;
        }

        if(msg->msg) {
            Hal_Mem_Free(msg->msg);
        }
        Hal_Mem_Free(msg);
    }
}

#ifdef BUILD_IN_PC_SIMULATOR
static void hal_wlan_adp_main_pc_task_cb(lv_task_t * task)
{
    hal_wlan_msg_t * msg = (hal_wlan_msg_t *)task->user_data;
    printf("%s: rcv msg id %d\n", __FUNCTION__, msg->id);
    switch(msg->id) {
    case HAL_WLAN_MSG_ID_OPEN_WLAN:
        hal_wlan_adp_open_wlan_msg();
        break;
    case HAL_WLAN_MSG_ID_CLOSE_WLAN:
        hal_wlan_adp_close_wlan_msg();
        break;
    case HAL_WLAN_MSG_ID_RESET:
        hal_wlan_adp_reset_msg();
        break;
    case HAL_WLAN_MSG_ID_SCAN_AP:
        hal_wlan_adp_scan_ap_msg();
        break;
    case HAL_WLAN_MSG_ID_SCAN_RESULT:
        hal_wlan_adp_scan_result_msg(msg->msg);
        break;
    case HAL_WLAN_MSG_ID_PERIODIC_SCAN:
        hal_wlan_adp_periodic_scan_msg();
        break;
    case HAL_WLAN_MSG_ID_OPEN_AP:
        hal_wlan_adp_open_ap_msg(msg->msg);
        break;
    case HAL_WLAN_MSG_ID_UI_STATE_CHG:
        hal_wlan_adp_ui_state_chg_msg(msg->msg);
        break;
    case HAL_WLAN_MSG_ID_DEL_NW:
        hal_wlan_adp_del_nw_msg(msg->msg);
        break;
    case HAL_WLAN_MSG_ID_SET_AUTO_SEL_NW:
        hal_wlan_adp_set_auto_sel_nw_msg(msg->msg);
        break;
    case HAL_WLAN_MSG_ID_DISCONNECT:
        hal_wlan_adp_disconnect_msg(msg->msg);
        break;
    case HAL_WLAN_MSG_ID_STA_UP:
        hal_wlan_adp_sta_up_msg();
        break;
    case HAL_WLAN_MSG_ID_STA_DOWN:
        hal_wlan_adp_sta_down_msg(msg->msg);
        break;
    case HAL_WLAN_MSG_ID_ACT_AP_RSSI:
        hal_wlan_adp_act_ap_rssi_msg(msg->msg);
        break;
    case HAL_WLAN_MSG_ID_LCD_WAKEUP:
        hal_wlan_adp_lcd_wakeup_msg();
        break;
    case HAL_WLAN_MSG_ID_NETIF_CONFIG:
        hal_wlan_adp_netif_config_msg();
        break;
    case HAL_WLAN_MSG_ID_GET_IP:
        hal_wlan_adp_get_ip_msg();
        break;
    case HAL_WLAN_MSG_ID_PROC_CONTINUE:
        hal_wlan_adp_proc_continue_msg();
        break;
    case HAL_WLAN_MSG_ID_HW_RESET_START:
        hal_wlan_adp_hw_reset_start_msg();
        break;
    case HAL_WLAN_MSG_ID_HW_RESET_END:
        hal_wlan_adp_hw_reset_end_msg();
        break;
    case HAL_WLAN_MSG_ID_OPEN_WLAN_WITHOUT_SECURITY:
        hal_wlan_adp_open_wlan_without_security_msg();
        break;
    case HAL_WLAN_MSG_ID_OPEN_NW_WITHOUT_SECURITY:
        hal_wlan_adp_open_nw_without_security_msg(msg->msg);
        break;
    case HAL_WLAN_MSG_ID_DEL_NW_WITHOUT_SECURITY:
        hal_wlan_adp_del_nw_without_security_msg(msg->msg);
        break;
    default:
        printf("%s: wrong msg %d\n", __FUNCTION__, msg->id);
        break;
    }
    if(msg->msg) {
        Hal_Mem_Free(msg->msg);
    }
    Hal_Mem_Free(msg);
}
#endif

static void hal_wlan_send_msg(HAL_WLAN_MSG_ID_T msg_id, void * data)
{
    printf("%s: rcv msg id %d\n", __FUNCTION__, msg_id);

#ifdef BUILD_IN_PC_SIMULATOR
    hal_wlan_msg_t * msg = (hal_wlan_msg_t *)Hal_Mem_Alloc(sizeof(hal_wlan_msg_t));
    msg->id = msg_id;
    msg->msg = data;
    static uint8_t msg_time = 10;
    lv_task_t * task = lv_task_create(hal_wlan_adp_main_pc_task_cb, msg_time,
                                      LV_TASK_PRIO_MID, msg);
    msg_time++;
    lv_task_once(task);
#else
    hal_wlan_msg_t * msg = (hal_wlan_msg_t *)Hal_Mem_Alloc(sizeof(hal_wlan_msg_t));
    msg->id = msg_id;
    msg->msg = data;
    Hal_Send_Message((TASK_ID)adp_task_id, msg);
#endif
}

static void hal_wlan_timer_start(uint8_t timer_id)
{
    if(HAL_WLAN_MAX_TIMER_NUM <= timer_id) {
        printf("%s: unknown timer id %d\n", __FUNCTION__, timer_id);
        return;
    }

    if(wlan_timer[timer_id].is_running) {
        printf("%s: timer %d has been started\n", __FUNCTION__, timer_id);
        return;
    }

#ifndef BUILD_IN_PC_SIMULATOR
    wlan_timer[timer_id].is_running = true;
    wlan_timer[timer_id].timeout_count = 0;
    switch(timer_id) {
    case HAL_WLAN_TIMER_ID_PERIOD_SCAN:
        uos_timer_start(wlan_timer[timer_id].id,
                        MS_TO_TICKS(HAL_WLAN_PERIODIC_SCAN_INTERVAL_MS),
                        MS_TO_TICKS(HAL_WLAN_PERIODIC_SCAN_INTERVAL_MS),
                        hal_wlan_periodic_scan_timeout_cb,
                        0);
        break;
    case HAL_WLAN_TIMER_ID_GET_IP:
        uos_timer_start(wlan_timer[timer_id].id,
                        MS_TO_TICKS(HAL_WLAN_GET_IP_TIMER_LEN),
                        MS_TO_TICKS(HAL_WLAN_GET_IP_TIMER_LEN),
                        hal_wlan_lwip_config_cb,
                        0);
        break;
    case HAL_WLAN_TIMER_ID_SCAN_PROTECT:
        uos_timer_start(wlan_timer[timer_id].id,
                        MS_TO_TICKS(2500),
                        MS_TO_TICKS(2500),
                        hal_wlan_scan_protect_timeout_cb,
                        0);
        break;
    case HAL_WLAN_TIMER_ID_CHECK_SDIO_CFG:
        uos_timer_start(wlan_timer[timer_id].id,
                        MS_TO_TICKS(HAL_WLAN_CHECK_SDIO_CONFIG_INTERVAL),
                        MS_TO_TICKS(HAL_WLAN_CHECK_SDIO_CONFIG_INTERVAL),
                        hal_wlan_check_sdio_config_timeout_cb,
                        0);
        break;
    }
#endif
}

static bool hal_wlan_timer_stop(uint8_t timer_id)
{
    if(HAL_WLAN_MAX_TIMER_NUM <= timer_id) {
        printf("%s: unknown timer id %d\n", __FUNCTION__, timer_id);
        return false;
    }

    if(!wlan_timer[timer_id].is_running) {
        printf("%s: timer %d is not started\n", __FUNCTION__, timer_id);
        return false;
    }

#ifndef BUILD_IN_PC_SIMULATOR
    wlan_timer[timer_id].is_running = false;
    uos_timer_stop(wlan_timer[timer_id].id);
#endif

    return true;
}

#endif/*USE_LV_WATCH_WLAN*/
